private void fixRemoteUrl(ResourceStoreRequest request) { if (overwriteRemoteUrl != null) { return; } if (P2Constants.SITE_XML.equals(request.getRequestPath())) { return; } try { RepositoryItemUid siteUID = createUid(P2Constants.SITE_XML); ResourceStoreRequest siteRequest = new ResourceStoreRequest(siteUID.getPath()); StorageFileItem siteItem; try { siteItem = (StorageFileItem) getLocalStorage().retrieveItem(this, siteRequest); } catch (ItemNotFoundException e) { siteItem = (StorageFileItem) getRemoteStorage().retrieveItem(this, siteRequest, getRemoteUrl()); } PlexusConfiguration plexusConfig = new XmlPlexusConfiguration( Xpp3DomBuilder.build(new InputStreamReader(siteItem.getInputStream()))); this.overwriteRemoteUrl = plexusConfig.getAttribute("url"); getLogger() .info("Remote update site does overwrite the remote url " + this.overwriteRemoteUrl); } catch (Exception e) { getLogger().debug(e.getMessage(), e); this.overwriteRemoteUrl = ""; } }
@Override public void storeItem(final ProxyRepository repository, final StorageItem item) throws UnsupportedStorageOperationException, RemoteStorageException { if (!(item instanceof StorageFileItem)) { throw new UnsupportedStorageOperationException( "Storing of non-files remotely is not supported!"); } final StorageFileItem fileItem = (StorageFileItem) item; final ResourceStoreRequest request = new ResourceStoreRequest(item); final URL remoteUrl = appendQueryString(getAbsoluteUrlFromBase(repository, request), repository); final HttpPut method = new HttpPut(remoteUrl.toExternalForm()); final InputStreamEntity entity; try { entity = new InputStreamEntity(fileItem.getInputStream(), fileItem.getLength()); } catch (IOException e) { throw new RemoteStorageException( e.getMessage() + " [repositoryId=\"" + repository.getId() + "\", requestPath=\"" + request.getRequestPath() + "\", remoteUrl=\"" + remoteUrl.toString() + "\"]", e); } entity.setContentType(fileItem.getMimeType()); method.setEntity(entity); final HttpResponse httpResponse = executeRequestAndRelease(repository, request, method); final int statusCode = httpResponse.getStatusLine().getStatusCode(); if (statusCode != HttpStatus.SC_OK && statusCode != HttpStatus.SC_CREATED && statusCode != HttpStatus.SC_NO_CONTENT && statusCode != HttpStatus.SC_ACCEPTED) { throw new RemoteStorageException( "Unexpected response code while executing " + method.getMethod() + " method [repositoryId=\"" + repository.getId() + "\", requestPath=\"" + request.getRequestPath() + "\", remoteUrl=\"" + remoteUrl.toString() + "\"]. Expected: \"any success (2xx)\". Received: " + statusCode + " : " + httpResponse.getStatusLine().getReasonPhrase()); } }
protected Model getPom(Variant variant, Request request, Response response) throws ResourceException { Form form = request.getResourceRef().getQueryAsForm(); // TODO: enable only one section retrieval of POM, ie. only mailing lists, or team members String groupId = form.getFirstValue("g"); String artifactId = form.getFirstValue("a"); String version = form.getFirstValue("v"); String repositoryId = form.getFirstValue("r"); if (groupId == null || artifactId == null || version == null || repositoryId == null) { throw new ResourceException(Status.CLIENT_ERROR_BAD_REQUEST); } ArtifactStoreRequest gavRequest = getResourceStoreRequest( request, false, repositoryId, groupId, artifactId, version, null, null, "pom"); try { MavenRepository mavenRepository = getMavenRepository(repositoryId); ArtifactStoreHelper helper = mavenRepository.getArtifactStoreHelper(); InputStream pomContent = null; InputStreamReader ir = null; Model pom = null; try { StorageFileItem file = helper.retrieveArtifactPom(gavRequest); pomContent = file.getInputStream(); MavenXpp3Reader reader = new MavenXpp3Reader(); ir = new InputStreamReader(pomContent); pom = reader.read(ir); } finally { IOUtil.close(pomContent); IOUtil.close(ir); } return pom; } catch (Exception e) { handleException(request, response, e); } return null; }
@Test public void hiddenTargetHandlingAtRoot() throws Exception { // test subject final DefaultFSPeer subject = new DefaultFSPeer(); // repo base File repoBase = new File("target/repoId"); // the file we want to store File target = new File(repoBase, "archetype-catalog.xml"); target.getParentFile().mkdirs(); final StorageFileItem file = Mockito.mock(StorageFileItem.class); Mockito.when(file.getPath()).thenReturn("/archetype-catalog.xml"); Mockito.when(file.getParentPath()).thenReturn("/"); // getting hidden target for target File hiddenTarget = subject.getHiddenTarget(null, repoBase, target, file); assertThat(hiddenTarget, notNullValue()); assertThat(hiddenTarget, isFile()); // startsWith, as garbage is appended to it's end assertThat(hiddenTarget.getName(), startsWith("archetype-catalog.xml")); // contains, as OS path from root is prefixing this, and garbage at the end suffixing it assertThat( hiddenTarget.getPath(), containsString( "target/repoId/.nexus/tmp/archetype-catalog.xml".replace("/", File.separator))); // writing to hidden target is handled elsewhere, so we simulate content being written out final String PAYLOAD = "dummy payload"; FileUtils.write(hiddenTarget, PAYLOAD); // handle the rename subject.handleRenameOperation(hiddenTarget, target); // hidden should cease to exist assertThat(hiddenTarget, not(exists())); // target should exists assertThat(target, exists()); // name should be not garbaged anymore assertThat(target.getName(), equalTo("archetype-catalog.xml")); // path prefixed by OS from root, no garbage at tail assertThat( target.getPath(), endsWith("target/repoId/archetype-catalog.xml".replace("/", File.separator))); // content is fine too assertThat(FileUtils.readFileToString(target), equalTo(PAYLOAD)); }
@Override public ContentLocator generateContent(Repository repository, String path, StorageFileItem item) throws IllegalOperationException, ItemNotFoundException, LocalStorageException { // make length unknown (since it will be known only in the moment of actual content pull) item.setLength(-1); return new ArchetypeContentLocator( repository.getId(), ((DefaultIndexerManager) indexerManager).getRepositoryIndexContext(repository), macPlugin, new ArtifactInfoFilter() { public boolean accepts(IndexingContext ctx, ArtifactInfo ai) { return indexArtifactFilter.filterArtifactInfo(ai); } }); }
/** * Validate an "XML like file" by searching for passed in patterns (using plain string matching), * consuming at most lines as passed in as parameter. * * @param file file who's content needs to be checked for. * @param expectedPattern the expected String pattern to search for. * @param linesToCheck amount of lines (as detected by Scanner) to consume during check. * @return {@link FileTypeValidity.VALID} if pattern found, {@link FileTypeValidity.INVALID} * otherwise. * @throws IOException in case of IO problem while reading file content. */ public static FileTypeValidity validateXmlLikeFile( final StorageFileItem file, final String expectedPattern, final int linesToCheck) throws IOException { int lineCount = 0; BufferedInputStream bis = null; try { bis = new BufferedInputStream(file.getInputStream()); Scanner scanner = new Scanner(bis); while (scanner.hasNextLine() && lineCount < linesToCheck) { lineCount++; String line = scanner.nextLine(); if (line.contains(expectedPattern)) { return FileTypeValidity.VALID; } } } finally { IOUtil.close(bis); } return FileTypeValidity.INVALID; }
public void doOnCollectionExit(WalkerContext context, StorageCollectionItem coll) throws Exception { if (getLogger().isDebugEnabled()) { getLogger().debug("onCollectionExit() :: " + coll.getRepositoryItemUid().toString()); } shouldProcessCollection = coll.getPath().endsWith("SNAPSHOT"); if (!shouldProcessCollection) { return; } deletableSnapshotsAndFiles.clear(); remainingSnapshotsAndFiles.clear(); removeWholeGAV = false; Gav gav = null; Collection<StorageItem> items; items = repository.list(false, coll); HashSet<Long> versionsToRemove = new HashSet<Long>(); // gathering the facts for (StorageItem item : items) { if (!item.isVirtual() && !StorageCollectionItem.class.isAssignableFrom(item.getClass())) { gav = ((MavenRepository) coll.getRepositoryItemUid().getRepository()) .getGavCalculator() .pathToGav(item.getPath()); if (gav != null) { // if we find a pom, check for delete on release if (!gav.isHash() && !gav.isSignature() && gav.getExtension().equals("pom")) { if (request.isRemoveIfReleaseExists() && releaseExistsForSnapshot(gav, item.getItemContext())) { getLogger().debug("Found POM and release exists, removing whole gav."); removeWholeGAV = true; // Will break out and junk whole gav break; } } item.getItemContext().put(Gav.class.getName(), gav); if (gav.getSnapshotTimeStamp() != null) { getLogger().debug("Using GAV snapshot timestamp"); long itemTimestamp = gav.getSnapshotTimeStamp().longValue(); getLogger().debug("NOW is " + itemTimestamp); // If this timestamp is already marked to be removed, junk it if (versionsToRemove.contains(new Long(itemTimestamp))) { addStorageFileItemToMap(deletableSnapshotsAndFiles, gav, (StorageFileItem) item); } else { getLogger() .debug("itemTimestamp=" + itemTimestamp + ", dateTreshold=" + dateThreshold); // if dateTreshold is not used (zero days) OR // if itemTimestamp is less then dateTreshold (NB: both are positive!) // below will the retentionCount overrule if needed this if (-1 == dateThreshold || itemTimestamp < dateThreshold) { versionsToRemove.add(new Long(itemTimestamp)); addStorageFileItemToMap(deletableSnapshotsAndFiles, gav, (StorageFileItem) item); } else { addStorageFileItemToMap(remainingSnapshotsAndFiles, gav, (StorageFileItem) item); } } } else { // If no timestamp on gav, then it is a non-unique snapshot // and should _not_ be removed getLogger() .debug("GAV Snapshot timestamp not available, skipping non-unique snapshot"); addStorageFileItemToMap(remainingSnapshotsAndFiles, gav, (StorageFileItem) item); } } } } // and doing the work here if (removeWholeGAV) { try { for (StorageItem item : items) { try { // preserve possible subdirs if (!(item instanceof StorageCollectionItem)) { repository.deleteItem(false, new ResourceStoreRequest(item)); } } catch (ItemNotFoundException e) { if (getLogger().isDebugEnabled()) { getLogger() .debug( "Could not delete whole GAV " + coll.getRepositoryItemUid().toString(), e); } } } } catch (Exception e) { getLogger() .warn("Could not delete whole GAV " + coll.getRepositoryItemUid().toString(), e); } } else { // and now check some things if (remainingSnapshotsAndFiles.size() < request.getMinCountOfSnapshotsToKeep()) { // do something if (remainingSnapshotsAndFiles.size() + deletableSnapshotsAndFiles.size() < request.getMinCountOfSnapshotsToKeep()) { // delete nothing, since there is less snapshots in total as allowed deletableSnapshotsAndFiles.clear(); } else { TreeSet<Version> keys = new TreeSet<Version>(deletableSnapshotsAndFiles.keySet()); while (!keys.isEmpty() && remainingSnapshotsAndFiles.size() < request.getMinCountOfSnapshotsToKeep()) { Version keyToMove = keys.last(); if (remainingSnapshotsAndFiles.containsKey(keyToMove)) { remainingSnapshotsAndFiles .get(keyToMove) .addAll(deletableSnapshotsAndFiles.get(keyToMove)); } else { remainingSnapshotsAndFiles.put( keyToMove, deletableSnapshotsAndFiles.get(keyToMove)); } deletableSnapshotsAndFiles.remove(keyToMove); keys.remove(keyToMove); } } } // NEXUS-814: is this GAV have remaining artifacts? boolean gavHasMoreTimestampedSnapshots = remainingSnapshotsAndFiles.size() > 0; for (Version key : deletableSnapshotsAndFiles.keySet()) { List<StorageFileItem> files = deletableSnapshotsAndFiles.get(key); deletedSnapshots++; for (StorageFileItem file : files) { try { // NEXUS-814: mark that we are deleting a TS snapshot, but there are still remaining // ones in repository. if (gavHasMoreTimestampedSnapshots) { file.getItemContext().put(MORE_TS_SNAPSHOTS_EXISTS_FOR_GAV, Boolean.TRUE); } gav = (Gav) file.getItemContext().get(Gav.class.getName()); repository.deleteItem(false, new ResourceStoreRequest(file)); deletedFiles++; } catch (ItemNotFoundException e) { if (getLogger().isDebugEnabled()) { getLogger().debug("Could not delete file:", e); } } catch (Exception e) { getLogger().info("Could not delete file:", e); } } } } removeDirectoryIfEmpty(coll); updateMetadataIfNecessary(context, coll); }
protected Object getContent( Variant variant, boolean redirectTo, Request request, Response response) throws ResourceException { Form form = request.getResourceRef().getQueryAsForm(); String groupId = form.getFirstValue("g"); String artifactId = form.getFirstValue("a"); String version = form.getFirstValue("v"); String packaging = form.getFirstValue("p"); String classifier = form.getFirstValue("c"); String repositoryId = form.getFirstValue("r"); String extension = form.getFirstValue("e"); if (groupId == null || artifactId == null || version == null || repositoryId == null) { throw new ResourceException(Status.CLIENT_ERROR_BAD_REQUEST); } // default the packaging if (StringUtils.isBlank(packaging)) { packaging = "jar"; } ArtifactStoreRequest gavRequest = getResourceStoreRequest( request, false, repositoryId, groupId, artifactId, version, packaging, classifier, extension); try { MavenRepository mavenRepository = getMavenRepository(repositoryId); ArtifactStoreHelper helper = mavenRepository.getArtifactStoreHelper(); StorageFileItem file = helper.retrieveArtifact(gavRequest); if (redirectTo) { Reference fileReference = createRepositoryReference( request, file.getRepositoryItemUid().getRepository().getId(), file.getRepositoryItemUid().getPath()); response.setLocationRef(fileReference); response.setStatus(Status.REDIRECTION_PERMANENT); String redirectMessage = "If you are not automatically redirected use this url: " + fileReference.toString(); return redirectMessage; } else { Representation result = new StorageFileItemRepresentation(file); result.setDownloadable(true); result.setDownloadName(file.getName()); return result; } } catch (Exception e) { handleException(request, response, e); } return null; }
private void mirrorUpdateSite(boolean force) throws StorageException, IllegalOperationException, UnsupportedStorageOperationException { UpdateSite site; try { RepositoryItemUid siteUID = createUid(P2Constants.SITE_XML); String oldSha1 = null; ResourceStoreRequest request = new ResourceStoreRequest(siteUID.getPath()); try { oldSha1 = getLocalStorage() .retrieveItem(this, request) .getAttributes() .get(DigestCalculatingInspector.DIGEST_SHA1_KEY); } catch (ItemNotFoundException e) { // it's okay } StorageFileItem siteItem = (StorageFileItem) doRetrieveRemoteItem(request); if (!force && oldSha1 != null && oldSha1.equals( siteItem.getAttributes().get(DigestCalculatingInspector.DIGEST_SHA1_KEY))) { return; } site = UpdateSite.read(siteItem.getInputStream()); } catch (Exception e) { throw new StorageException("Could not read site.xml", e); } List<FeatureRef> features = site.getFeatures(); getLogger().info("Mirroring " + features.size() + " features from update site " + getName()); final Set<String> mirrored = new HashSet<String>(); for (IFeatureRef feature : features) { mirrorFeature(site, feature, mirrored); } ResourceStoreRequest root = new ResourceStoreRequest(RepositoryItemUid.PATH_ROOT); DefaultWalkerContext ctx = new DefaultWalkerContext(this, root, filter); ctx.getContext().put("mirrored", mirrored); ctx.getProcessors() .add( new AbstractWalkerProcessor() { @SuppressWarnings("unchecked") @Override public void processItem(WalkerContext context, StorageItem item) throws Exception { Set<String> mirrored = (Set<String>) context.getContext().get("mirrored"); if (item.getRepositoryItemUid().getBooleanAttributeValue(IsHiddenAttribute.class)) { return; } if (item instanceof StorageFileItem && !mirrored.contains(item.getPath().substring(1))) { doDeleteItem(new ResourceStoreRequest(item.getPath())); } } }); getWalker().walk(ctx); getLogger().debug("Generating P2 metadata for Eclipse Update Site " + getName()); File baseDir = getLocalStorage().getBaseDir(this, root); File metadataDir = new File(baseDir, ".p2"); try { FileUtils.deleteDirectory(metadataDir); } catch (IOException e) { getLogger().warn("Unexpected IOException", e); } p2.generateSiteMetadata(baseDir, metadataDir, getName()); try { importFile(metadataDir, P2Constants.ARTIFACTS_PATH); importFile(metadataDir, P2Constants.CONTENT_PATH); FileUtils.deleteDirectory(metadataDir); } catch (IOException e) { // TODO this can actually happen on Windows getLogger().warn("Unexpected IOException", e); } }