/**
* Copyright (C) 2003-2007 eXo Platform SAS.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Affero General Public License
* as published by the Free Software Foundation; either version 3
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, see<http://www.gnu.org/licenses/>.
*/
package org.exoplatform.services.jcr.ext.artifact;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;
import org.exoplatform.container.xml.InitParams;
import org.exoplatform.container.xml.PropertiesParam;
import org.exoplatform.services.jcr.RepositoryService;
import org.exoplatform.services.jcr.access.AccessControlEntry;
import org.exoplatform.services.jcr.config.RepositoryConfigurationException;
import org.exoplatform.services.jcr.core.ExtendedNode;
import org.exoplatform.services.jcr.core.ManageableRepository;
import org.exoplatform.services.jcr.core.nodetype.ExtendedNodeTypeManager;
import org.exoplatform.services.jcr.core.nodetype.NodeTypeDataManager;
import org.exoplatform.services.jcr.ext.common.SessionProvider;
import org.exoplatform.services.jcr.ext.registry.RegistryEntry;
import org.exoplatform.services.jcr.ext.registry.RegistryService;
import org.exoplatform.services.log.ExoLogger;
import org.exoplatform.services.log.Log;
import org.picocontainer.Startable;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.xml.sax.SAXException;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;
import javax.jcr.Node;
import javax.jcr.NodeIterator;
import javax.jcr.PathNotFoundException;
import javax.jcr.Property;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.nodetype.NodeType;
import javax.jcr.query.Query;
import javax.jcr.query.QueryManager;
import javax.jcr.query.QueryResult;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamWriter;
/**
* Created by The eXo Platform SAS .<br/>
* Service responsible for Administration Maven repository the served JCR structure inside
* workspaceName is: rootPath (maven-root)/ ---part-of-group-folder1/ (nt:folder + exo:groupId)
* ---part-of-group-foldern/ ------artifact-root-folder/(nt:folder + exo:artifactId)
* ---------maven-metadata.xml(nt:file) ---------maven-metadata.xml.sha1(nt:file)
* ---------artifact-version-folder/(nt:folder + exo:versionId) ------------artifactId-version.jar
* (nt:file + exo:mavenjar / nt:resource) ------------artifactId-version.jar.sha1 (nt:file +
* exo:mavensha1 / nt:resource ) ------------artifactId-version.pom (nt:file + exo:mavenpom /
* nt:resource) ------------artifactId-version.pom.sha1 (nt:file + exo:mavensha1/ (nt:resource)
* ------------maven-metadata.xml (nt:file +exo:mavenmetadata / (nt:resource )
* ------------maven-metadata.xml.sha1(nt:file + exo:mavensha1 / (nt:resource)
*
* @author Gennady Azarenkov
* @author Volodymyr Krasnikov
* @version $Id: $
*/
public class ArtifactManagingServiceImpl
implements ArtifactManagingService, Startable
{
private static final int BUFFER = 4096;
private static final String STRING_TERMINATOR = "*";
private static final String NT_FILE = "artifact-nodetypes.xml";
private static final String SERVICE_NAME = "ArtifactManaging";
private RepositoryService repositoryService;
private RegistryService registryService;
private SessionProvider sessionProvider;
private InitParams initParams;
private String repoWorkspaceName;
private String rootNodePath;
private static final Log LOG = ExoLogger.getLogger(ArtifactManagingServiceImpl.class);
private Map<String, String> mimeMap = new Hashtable<String, String>();
private List<String> listErrorPom = new ArrayList<String>();
/**
* @param params
* @param repositoryService
* @param registryService
* @throws RepositoryConfigurationException
*/
public ArtifactManagingServiceImpl(InitParams initParams, RepositoryService repositoryService,
RegistryService registryService) throws RepositoryConfigurationException
{
this.repositoryService = repositoryService;
this.registryService = registryService;
if (initParams == null)
{
throw new RepositoryConfigurationException("Init parameters expected !!!");
}
this.initParams = initParams;
setDefaultMimes();
}
/**
* without registry service
*
* @param params
* @param repositoryService
* @throws RepositoryConfigurationException
*/
public ArtifactManagingServiceImpl(InitParams params, RepositoryService repositoryService)
throws RepositoryConfigurationException
{
this(params, repositoryService, null);
}
/*
* (non-Javadoc)
* @see org.exoplatform.services.jcr.ext.maven.ArtifactManagingService#addArtifact
* (org.exoplatform.services.jcr.ext.common.SessionProvider,
* org.exoplatform.services.jcr.ext.maven.ArtifactDescriptor, java.io.InputStream)
*/
public void addArtifact(SessionProvider sp, ArtifactDescriptor artifact, InputStream jarIStream,
InputStream pomIStream) throws RepositoryException
{
Session session = currentSession(sp);
Node rootNode = (Node) session.getItem(rootNodePath);
Node groupId_tail = createGroupIdLayout(rootNode, artifact);
Node artifactId_node = createArtifactIdLayout(groupId_tail, artifact);
Node version_node = createVersionLayout(artifactId_node, artifact);
if (version_node != null)
{ // returns if the same node sibling appears
importResource(version_node, jarIStream, "jar", artifact);
importResource(version_node, pomIStream, "pom", artifact);
}
session.save();
}
/*
* (non-Javadoc)
* @see org.exoplatform.services.jcr.ext.maven.ArtifactManagingService#exportArtifacts
* (org.exoplatform.services.jcr.ext.common.SessionProvider,
* org.exoplatform.services.jcr.ext.maven.FolderDescriptor, java.io.OutputStream)
*/
public void exportArtifacts(SessionProvider sp, FolderDescriptor parentFolder, OutputStream out)
throws RepositoryException, FileNotFoundException
{
Session session = currentSession(sp);
Node parentNode;
if (rootNodePath.length() > 1)
{
parentNode = (Node) session.getItem(rootNodePath + "/" + parentFolder.getAsPath());
}
else
{
parentNode = (Node) session.getItem("/" + parentFolder.getAsPath());
}
LOG.info("Write repository to zipped stream");
ZipOutputStream zout = new ZipOutputStream(new BufferedOutputStream(out, BUFFER));
try
{
mapRepositoryToZipStream(parentNode, zout);
zout.flush();
zout.close();
}
catch (IOException e)
{
LOG.error("Cannot write to zip stream", e);
}
}
public void exportArtifacts(SessionProvider sp, FolderDescriptor parentFolder, File destFolder)
throws RepositoryException, FileNotFoundException
{
Session session = currentSession(sp);
Node parentNode;
if (rootNodePath.length() > 1)
{
parentNode = (Node) session.getItem(rootNodePath + "/" + parentFolder.getAsPath());
}
else
{
parentNode = (Node) session.getItem("/" + parentFolder.getAsPath());
}
mapRepositoryToFilefs(parentNode, destFolder);
}
private void mapRepositoryToFilefs(Node parentNode, File parentFolder) throws RepositoryException
{
NodeIterator folderIterator = parentNode.getNodes();
while (folderIterator.hasNext())
{
Node folder = folderIterator.nextNode();
if (folder.isNodeType("exo:artifact"))
{
File levelfolder = new File(parentFolder.getAbsoluteFile() + File.separator + folder.getName());
levelfolder.mkdir();
mapRepositoryToFilefs(folder, levelfolder); // recursive call
}
else if (folder.isNodeType("exo:file"))
{
File content = new File(parentFolder + File.separator + folder.getName());
FileOutputStream fout = null;
try
{
fout = new FileOutputStream(content);
Node dataNode = folder.getNode("jcr:content");
Property data = dataNode.getProperty("jcr:data");
Property lastModified = dataNode.getProperty("jcr:lastModified");
content.setLastModified(lastModified.getLong());
IOUtils.copy(data.getStream(), fout);
}
catch (FileNotFoundException e)
{
LOG.error("!!Can't create content fo file", e);
}
catch (IOException e)
{
LOG.error("!!Can't write content fo file", e);
}
finally
{
IOUtils.closeQuietly(fout);
}
}
}
}
private void mapRepositoryToZipStream(Node parentNode, ZipOutputStream zout) throws RepositoryException, IOException
{
NodeIterator folderIterator = parentNode.getNodes();
while (folderIterator.hasNext())
{
Node folder = folderIterator.nextNode();
if (folder.isNodeType("exo:artifact"))
{
String entryName = parentNode.getPath() + File.separator + folder.getName();
ZipEntry entry = new ZipEntry(entryName + "/");
zout.putNextEntry(entry);
mapRepositoryToZipStream(folder, zout);
}
else if (folder.isNodeType("exo:file"))
{
String entryName = parentNode.getPath() + File.separator + folder.getName();
ZipEntry entry = new ZipEntry(entryName);
if (LOG.isDebugEnabled())
{
LOG.debug("Zipping " + entryName);
}
Node dataNode = folder.getNode("jcr:content");
Property data = dataNode.getProperty("jcr:data");
InputStream in = data.getStream();
Property lastModified = dataNode.getProperty("jcr:lastModified");
entry.setTime(lastModified.getLong());
entry.setSize(in.available());
zout.putNextEntry(entry);
int count;
byte[] buf = new byte[BUFFER];
while ((count = in.read(buf, 0, BUFFER)) != -1)
{
zout.write(buf, 0, count);
}
zout.flush();
in.close();
}
}
}
/*
* (non-Javadoc)
* @see org.exoplatform.services.jcr.ext.maven.ArtifactManagingService#getDescriptors
* (org.exoplatform.services.jcr.ext.common.SessionProvider,
* org.exoplatform.services.jcr.ext.maven.FolderDescriptor)
*/
public List<Descriptor> getDescriptors(SessionProvider sp, FolderDescriptor parentFolder) throws RepositoryException
{
LOG.info("Get child nodes to : " + parentFolder.getAsString());
Session session = currentSession(sp);
session.refresh(true);
Node rootNode = (Node) session.getItem(rootNodePath);
String strPath = parentFolder.getAsString();
Node targetNode;
if (strPath.equals("/"))
{
targetNode = rootNode;
}
else
{
targetNode = rootNode.getNode(strPath.substring(1));
}
LOG.info(targetNode.getPath());
NodeType[] a = targetNode.getMixinNodeTypes();
StringBuilder mixins = new StringBuilder();
for (NodeType type : a)
{
mixins.append(type.getName()).append(" ");
}
LOG.info("**** Mixins : " + mixins.toString());
LOG.info("**** Workspace : " + session.getWorkspace().getName());
List<Descriptor> childNodes = new ArrayList<Descriptor>();
for (NodeIterator iterator = targetNode.getNodes(); iterator.hasNext();)
{
// descriptor holds names of all child nodes than makes up artifact
// coordinates.
Node node = iterator.nextNode();
if (node.isNodeType("nt:folder") || node.isNodeType("nt:file"))
{
Descriptor descriptor = new FolderDescriptor(node.getName());
childNodes.add(descriptor);
}
}
return (childNodes.size() == 0) ? null : childNodes;
}
/*
* (non-Javadoc)
* @see org.exoplatform.services.jcr.ext.maven.ArtifactManagingService#importArtifacts
* (org.exoplatform.services.jcr.ext.common.SessionProvider, java.io.InputStream)
*/
public void importArtifacts(SessionProvider sp, InputStream in) throws RepositoryException, FileNotFoundException
{
LOG.info("Extract repository to temporary folder");
String path = System.getProperty("java.io.tmpdir") + File.separator + "maven2";
File temporaryFolder = new File(getUniqueFilename(path));
if (!temporaryFolder.mkdir())
{
throw new FileNotFoundException("Cannot create temporary folder");
}
ZipEntry entry;
ZipInputStream zipIn = new ZipInputStream(new BufferedInputStream(in));
try
{
while ((entry = zipIn.getNextEntry()) != null)
{
if (!(entry.isDirectory() && new File(temporaryFolder + File.separator + entry.getName()).mkdir()))
{
int count;
byte data[] = new byte[BUFFER];
File file = new File(temporaryFolder + File.separator + entry.getName());
FileUtils.touch(file);
FileOutputStream fos = new FileOutputStream(file);
BufferedOutputStream dest = new BufferedOutputStream(fos, BUFFER);
while ((count = zipIn.read(data, 0, BUFFER)) != -1)
{
dest.write(data, 0, count);
}
dest.flush();
dest.close();
}
}
}
catch (IOException e)
{
LOG.error("Cannot get zip entry from stream", e);
}
finally
{
IOUtils.closeQuietly(zipIn);
IOUtils.closeQuietly(in);
}
// main part - copy to JCR from temp folder
// use uploading artifacts from local folder.
importArtifacts(sp, temporaryFolder);
try
{
FileUtils.deleteDirectory(temporaryFolder);
}
catch (IOException e)
{
LOG.error("Cannot remove temporary folder", e);
}
}
/*
* (non-Javadoc)
* @see org.exoplatform.services.jcr.ext.maven.ArtifactManagingService#importArtifacts
* (org.exoplatform.services.jcr.ext.common.SessionProvider, java.io.File)
*/
public void importArtifacts(SessionProvider sp, File folder) throws RepositoryException, FileNotFoundException
{
if (!folder.exists())
throw new FileNotFoundException("Source folder expected");
try
{
this.listErrorPom.clear();
importFilesToJCR(sp, folder);
}
catch (Exception e)
{
LOG.error("Exception during uploading local folder to JCR", e);
}
}
/*
* This method provides adding to JCR artifacts. this means that jar-files and appropriate pom
* files would be added. Main logic: scan all files & if it is a pair jar/pom -add it.
*/
private void importFilesToJCR(SessionProvider sp, File folder) throws Exception
{
for (File file : folder.listFiles(new DefaultFileFilter()))
{
if (file.isDirectory())
{
importFilesToJCR(sp, file);
}
String ext = FilenameUtils.getExtension(file.getAbsolutePath());
if (ext.equals("pom"))
{
String basename = FilenameUtils.removeExtension(file.getAbsolutePath());
File jarfile = new File(basename.concat(".jar"));
if (jarfile.exists())
{
// get descripting from pom file
try
{
ArtifactDescriptor artifact = ArtifactDescriptor.createFromPomfile(file);
InputStream jarIStream = new FileInputStream(jarfile);
InputStream pomIStream = new FileInputStream(file);
addArtifact(sp, artifact, jarIStream, pomIStream);
}
catch (org.xml.sax.SAXParseException e)
{
// throw new ArtifactDescriptorException(FilenameUtils.getName(file.getAbsolutePath()));
this.listErrorPom.add(FilenameUtils.getName(file.getAbsolutePath()));
continue;
}
}
}
}
}
/*
* According JCR structure, version Node holds all actual data: jar, pom and ckecksums Removing
* that node is removing all content and artifact indeed!
* @see org.exoplatform.services.jcr.ext.maven.ArtifactManagingService#removeArtifact
* (org.exoplatform.services.jcr.ext.common.SessionProvider,
* org.exoplatform.services.jcr.ext.maven.ArtifactDescriptor)
*/
public void removeArtifact(SessionProvider sp, Descriptor artifact) throws RepositoryException
{
Session session = currentSession(sp);
Node root = (Node) session.getItem(rootNodePath);
String pathToRemove = "";
if (rootNodePath.length() > 1)
{
if (rootNodePath.endsWith("/"))
pathToRemove = rootNodePath + artifact.getAsPath();
else
pathToRemove = rootNodePath + "/" + artifact.getAsPath();
}
else
{
pathToRemove = "/" + artifact.getAsPath();
}
if (LOG.isDebugEnabled())
{
LOG.debug("Remove node: " + pathToRemove);
}
Node rmNode = (Node) session.getItem(pathToRemove);
// while (rmNode != root) {
// Node parent = rmNode.getParent();
rmNode.remove();
// if (!parent.hasNodes())
// rmNode = parent;
// else
// break;
// }
session.save();
}
public List getPermission(SessionProvider sp, Descriptor artifact) throws RepositoryException
{
Session session = currentSession(sp);
String pathToCheck = "";
if (rootNodePath.length() > 1)
{ // artifact root is some real node
if (rootNodePath.endsWith("/"))
pathToCheck = rootNodePath + artifact.getAsPath();
else
pathToCheck = rootNodePath + "/" + artifact.getAsPath();
}
else
{
pathToCheck = "/" + artifact.getAsPath(); // "/" - is root path
}
LOG.debug("Checking Permission on node: " + pathToCheck);
ExtendedNode rmNode = (ExtendedNode) session.getItem(pathToCheck);
List<AccessControlEntry> list = rmNode.getACL().getPermissionEntries();
return list;
}
public void changePermission(SessionProvider sp, Descriptor artifact, String identity, String[] permissions,
boolean delete) throws RepositoryException
{
Session session = currentSession(sp);
String pathToChange = "";
if (rootNodePath.length() > 1)
{ // artifact root is some real node
if (rootNodePath.endsWith("/"))
pathToChange = rootNodePath + artifact.getAsPath();
else
pathToChange = rootNodePath + "/" + artifact.getAsPath();
}
else
{
pathToChange = "/" + artifact.getAsPath(); // "/" - is root path
}
LOG.debug("Changing Permission on node: " + pathToChange);
ExtendedNode chNode = (ExtendedNode) session.getItem(pathToChange);
if (!chNode.isNodeType("exo:privilegeable"))
{
if (chNode.canAddMixin("exo:privilegeable"))
chNode.addMixin("exo:privilegeable");
else
throw new RepositoryException("Can't add mixin");
}
// log.info("PERMS-SIZE:" + permissions.length);
try
{
if (!delete)
chNode.setPermission(identity, permissions);
else
{
if (permissions.length > 0)
{
for (int i = 0; i < permissions.length; i++)
chNode.removePermission(identity, permissions[i]);
}
else
{
chNode.removePermission(identity);
}
}
}
catch (RepositoryException e)
{
LOG.error("Cannot change permissions", e);
}
session.save();
}
/*
* (non-Javadoc)
* @see org.exoplatform.services.jcr.ext.maven.ArtifactManagingService#searchArtifacts
* (org.exoplatform.services.jcr.ext.common.SessionProvider,
* org.exoplatform.services.jcr.ext.maven.SearchCriteria)
*/
public List<Descriptor> searchArtifacts(SessionProvider sp, SearchCriteria criteria) throws RepositoryException
{
Session session = currentSession(sp);
session.refresh(true);
session.save();
String param = criteria.getContainsExpr();
String pathConstraint = "";
if (rootNodePath.length() > 1)
{ // artifact root is some real node
if (rootNodePath.endsWith("/"))
pathConstraint = rootNodePath + "%/" + param + "[%]";
else
pathConstraint = rootNodePath + "/%/" + param + "[%]";
}
else
{
pathConstraint = "/%/" + param + "[%]"; // artifact root is workspace root
}
// node !!
String sqlQuery = String.format("SELECT * FROM nt:folder WHERE jcr:path LIKE '%s' ", pathConstraint);
LOG.info(sqlQuery);
QueryManager manager = session.getWorkspace().getQueryManager();
Query query = manager.createQuery(sqlQuery, Query.SQL);
QueryResult queryResult = query.execute();
NodeIterator iterator = queryResult.getNodes();
List<Descriptor> preciseNode = new ArrayList<Descriptor>();
while (iterator.hasNext())
{
Node candidate = iterator.nextNode();
Descriptor descriptor = new FolderDescriptor(candidate.getPath());
preciseNode.add(descriptor);
}
return preciseNode;
}
/*
* (non-Javadoc)
* @see org.picocontainer.Startable#start()
*/
public void start()
{
// responsible for:
// 1. reading parameters (such as repoWorkspaceName, repoPath) from
// registryService (if present) or init params
// 2. initializing artifact service Registry Entry if registryService is
// present
// if Entry is not initialized yet (first launch)
// 3. initializing maven root if not initialized
if (LOG.isDebugEnabled())
{
LOG.debug("Starting ArtifactManagingService ...");
}
sessionProvider = SessionProvider.createSystemProvider();
try
{
InputStream xml = getClass().getResourceAsStream(NT_FILE);
ManageableRepository rep = repositoryService.getCurrentRepository();
rep.getNodeTypeManager().registerNodeTypes(xml, ExtendedNodeTypeManager.IGNORE_IF_EXISTS,
NodeTypeDataManager.TEXT_XML);
readParamsFromRegistryService(sessionProvider);
prepareRootNode(sessionProvider, rootNodePath);
}
catch (PathNotFoundException e)
{
try
{
readParamsFromFile();
writeParamsToRegistryService(sessionProvider);
prepareRootNode(sessionProvider, rootNodePath);
}
catch (RepositoryException exc)
{
LOG.error("Cannot write init configuration to RegistryService", exc);
}
catch (IOException exc)
{
LOG.error("Cannot write init configuration to RegistryService", exc);
}
catch (SAXException exc)
{
LOG.error("Cannot write init configuration to RegistryService", exc);
}
catch (ParserConfigurationException exc)
{
LOG.error("Cannot write init configuration to RegistryService", exc);
}
}
catch (RepositoryException e)
{
LOG.error("Error while register nodetypes/checking existance", e);
}
finally
{
sessionProvider.close();
}
}
/*
* (non-Javadoc)
* @see org.picocontainer.Startable#stop()
*/
public void stop()
{
}
private Session currentSession(SessionProvider sp) throws RepositoryException
{
return sp.getSession(repoWorkspaceName, repositoryService.getCurrentRepository());
}
private void prepareRootNode(SessionProvider sp, String path) throws RepositoryException
{
Session session = currentSession(sp);
Node current_root = session.getRootNode();
for (String folder : path.split("/"))
{
if (!current_root.hasNode(folder))
{
current_root.addNode(folder);
}
current_root = current_root.getNode(folder);
}
session.save();
if (!session.getItem(path).isNode())
throw new RepositoryException("Maven root node is not been initialized");
}
// this function creates hierarchy in JCR storage acording to groupID
// parameter : com.google.code...
private Node createGroupIdLayout(Node rootNode, ArtifactDescriptor artifact) throws RepositoryException
{
FolderDescriptor groupId = artifact.getGroupId();
List<String> struct_groupId = new ArrayList<String>();
String[] items = groupId.getAsPath().split("/");
for (String subString : items)
{
struct_groupId.add(subString);
}
Node groupIdTail = rootNode;
for (Iterator<String> iterator = struct_groupId.iterator(); iterator.hasNext();)
{
String name = iterator.next();
Node levelNode;
// Node do not has such child nodes
if (!groupIdTail.hasNode(name))
{
levelNode = groupIdTail.addNode(name, "nt:folder");
levelNode.addMixin("exo:groupId");
}
else
{
levelNode = groupIdTail.getNode(name);
}
groupIdTail = levelNode;
}
return groupIdTail;
}
private Node createArtifactIdLayout(Node groupId_NodeTail, ArtifactDescriptor artifact) throws RepositoryException
{
String artifactId = artifact.getArtifactId();
Node artifactIdNode;
if (!groupId_NodeTail.hasNode(artifactId))
{
artifactIdNode = groupId_NodeTail.addNode(artifactId, "nt:folder");
artifactIdNode.addMixin("exo:artifactId");
artifactIdNode.setProperty("exo:versionList", new String[]
{ArtifactManagingServiceImpl.STRING_TERMINATOR, ArtifactManagingServiceImpl.STRING_TERMINATOR});
}
else
{
artifactIdNode = groupId_NodeTail.getNode(artifactId);
}
return artifactIdNode;
}
private Node createVersionLayout(Node artifactId, ArtifactDescriptor artifact) throws RepositoryException
{
String version = artifact.getVersionId();
if (artifactId.hasNode(version))
return null;
Node currentVersion = artifactId.addNode(version, "nt:folder");
currentVersion.addMixin("exo:versionId");
return currentVersion;
}
// this method used for writing to repo jars, poms and their checksums
private void importResource(Node parentNode, InputStream file_in, String resourceType, ArtifactDescriptor artifact)
throws RepositoryException
{
// Note that artifactBean been initialized within constructor
// resourceType can be jar, pom, metadata
String filename;
if (resourceType.equals("metadata"))
{
filename = "maven-metadata.xml";
}
else
{
filename = String.format("%s-%s.%s", artifact.getArtifactId(), artifact.getVersionId(), resourceType);
}
OutputStream fout = null;
File tmp_file = null;
try
{
String tmpFilename = getUniqueFilename(filename);
tmp_file = File.createTempFile(tmpFilename, null);
fout = new FileOutputStream(tmp_file);
IOUtils.copy(file_in, fout);
fout.flush();
}
catch (FileNotFoundException e)
{
LOG.error("Cannot create .tmp file for storing artifact", e);
}
catch (IOException e)
{
LOG.error("IO exception on .tmp file for storing artifact", e);
}
finally
{
IOUtils.closeQuietly(file_in);
IOUtils.closeQuietly(fout);
}
writePrimaryContent(parentNode, filename, resourceType, tmp_file);
writeChecksum(parentNode, filename, tmp_file, "SHA1");
try
{
// and collect all garbage : temporary files
FileUtils.forceDelete(tmp_file);
}
catch (IOException e)
{
LOG.error("Cannot delete tmp file", e);
}
}
private void writePrimaryContent(Node parentNode, String filename, String resourceType, File srcFile)
throws RepositoryException
{
String mimeType = getRelativeMimeType(resourceType);
Node nodeResourceFile = parentNode.addNode(filename, "nt:file");
String mixinType = "exo:maven".concat(resourceType);
if (nodeResourceFile.canAddMixin(mixinType))
nodeResourceFile.addMixin(mixinType);
try
{
InputStream file_is = new FileInputStream(srcFile);
Node content = nodeResourceFile.addNode("jcr:content", "nt:resource");
content.setProperty("jcr:mimeType", mimeType);
content.setProperty("jcr:lastModified", Calendar.getInstance());
content.setProperty("jcr:data", file_is);
IOUtils.closeQuietly(file_is);
}
catch (FileNotFoundException e)
{
LOG.error("Cannot read from .tmp resource file", e);
}
}
private void writeChecksum(Node parentNode, String filename, File srcFile, String algorithm)
throws RepositoryException
{
Node nodeChecksumFile = parentNode.addNode(filename.concat("." + algorithm.toLowerCase()), "nt:file");
String mixinType = "exo:maven".concat(algorithm.toLowerCase());
if (nodeChecksumFile.canAddMixin(mixinType))
{
nodeChecksumFile.addMixin(mixinType);
}
try
{
FileInputStream fileInputStream = new FileInputStream(srcFile);
String checksum = CRCGenerator.getChecksum(fileInputStream, algorithm);
InputStream checksum_is = new ByteArrayInputStream(checksum.getBytes());
String mimeType = "text/plain";
Node content = nodeChecksumFile.addNode("jcr:content", "nt:resource");
content.setProperty("jcr:mimeType", mimeType);
content.setProperty("jcr:lastModified", Calendar.getInstance());
content.setProperty("jcr:data", checksum_is);
IOUtils.closeQuietly(checksum_is);
}
catch (FileNotFoundException e)
{
LOG.error("Cannot read from .tmp resource file", e);
}
catch (IOException e)
{
LOG.error("Cannot read from .tmp resource file", e);
}
catch (NoSuchAlgorithmException e)
{
LOG.error("No such algorithm for generating checksums", e);
}
}
protected File createSingleMetadata(String groupId, String artifactId, String version) throws FileNotFoundException
{
File temp = null;
try
{
String filename = getUniqueFilename("maven-metadata.xml");
temp = File.createTempFile(filename, null);
OutputStream os = new FileOutputStream(temp);
XMLOutputFactory factory = XMLOutputFactory.newInstance();
XMLStreamWriter writer = factory.createXMLStreamWriter(os);
try
{
writer.writeStartDocument("UTF-8", "1.0");
writer.writeStartElement("metadata");
writer.writeStartElement("groupId");
writer.writeCharacters(groupId);
writer.writeEndElement();
writer.writeStartElement("artifactId");
writer.writeCharacters(artifactId);
writer.writeEndElement();
writer.writeStartElement("version");
writer.writeCharacters(version);
writer.writeEndElement();
writer.writeEndElement();
writer.writeEndDocument();
}
finally
{
writer.flush();
writer.close();
os.close();
}
}
catch (XMLStreamException e)
{
LOG.error("Error on creating metadata - XML", e);
}
catch (IOException e)
{
LOG.error("Error on creating metadata - FILE", e);
}
return (temp != null && temp.exists()) ? temp : null;
}
protected File createMultiMetadata(String groupId, String artifactId, String current_version, List<String> v_list)
throws FileNotFoundException
{
File temp = null;
try
{
String filename = getUniqueFilename("maven-metadata.xml");
temp = File.createTempFile(filename, null);
OutputStream os = new FileOutputStream(temp);
XMLOutputFactory factory = XMLOutputFactory.newInstance();
XMLStreamWriter writer = factory.createXMLStreamWriter(os);
try
{
writer.writeStartDocument("UTF-8", "1.0");
writer.writeStartElement("metadata");
writer.writeStartElement("groupId");
writer.writeCharacters(groupId);
writer.writeEndElement();
writer.writeStartElement("artifactId");
writer.writeCharacters(artifactId);
writer.writeEndElement();
String elderVersion;
if (v_list.size() > 0)
{
Collections.sort(v_list); // sort list
elderVersion = v_list.get(0); // get first element
}
else
elderVersion = current_version;
v_list.add(current_version);
writer.writeStartElement("version");
writer.writeCharacters(elderVersion);
writer.writeEndElement();
writer.writeStartElement("versions");
writer.writeStartElement("versioning");
for (Iterator<String> iterator = v_list.iterator(); iterator.hasNext();)
{
writer.writeStartElement("version");
writer.writeCharacters(iterator.next());
writer.writeEndElement();
}
writer.writeEndElement();
writer.writeEndElement();
writer.writeEndElement();
writer.writeEndDocument();
}
finally
{
writer.flush();
writer.close();
os.close();
}
}
catch (XMLStreamException e)
{
LOG.error("Error on creating metadata - XML", e);
}
catch (IOException e)
{
LOG.error("Error on creating metadata - FILE", e);
}
return (temp != null && temp.exists()) ? temp : null;
}
private String getRelativeMimeType(String key)
{
return (String) mimeMap.get(key);
}
private void setDefaultMimes()
{
mimeMap.put("jar", "application/java-archive");
mimeMap.put("pom", "text/xml");
// mimeMap.put("metadata", "text/xml");
}
private String getUniqueFilename(String basename)
{
String suffix = ((Double) Math.random()).toString().substring(2, 7);
return basename + "." + suffix;
}
/**
* Read parameters from RegistryService.
*
* @param sessionProvider
* The SessionProvider
* @throws RepositoryException
* @throws PathNotFoundException
*/
private void readParamsFromRegistryService(SessionProvider sessionProvider) throws PathNotFoundException,
RepositoryException
{
String entryPath = RegistryService.EXO_SERVICES + "/" + SERVICE_NAME + "/" + "workspace";
RegistryEntry registryEntry = registryService.getEntry(sessionProvider, entryPath);
Document doc = registryEntry.getDocument();
Element element = doc.getDocumentElement();
repoWorkspaceName = getAttributeSmart(element, "value");
entryPath = RegistryService.EXO_SERVICES + "/" + SERVICE_NAME + "/" + "rootNode";
registryEntry = registryService.getEntry(sessionProvider, entryPath);
doc = registryEntry.getDocument();
element = doc.getDocumentElement();
rootNodePath = getAttributeSmart(element, "value");
LOG.info("Workspace from RegistryService: " + repoWorkspaceName);
LOG.info("RootNode from RegistryService: " + rootNodePath);
}
/**
* Write parameters to RegistryService.
*
* @param sessionProvider
* The SessionProvider
* @throws ParserConfigurationException
* @throws SAXException
* @throws IOException
* @throws RepositoryException
*/
private void writeParamsToRegistryService(SessionProvider sessionProvider) throws IOException, SAXException,
ParserConfigurationException, RepositoryException
{
Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
Element root = doc.createElement(SERVICE_NAME);
doc.appendChild(root);
Element element = doc.createElement("workspace");
setAttributeSmart(element, "value", repoWorkspaceName);
root.appendChild(element);
element = doc.createElement("rootNode");
setAttributeSmart(element, "value", rootNodePath);
root.appendChild(element);
RegistryEntry serviceEntry = new RegistryEntry(doc);
registryService.createEntry(sessionProvider, RegistryService.EXO_SERVICES, serviceEntry);
}
/**
* Get attribute value.
*
* @param element
* The element to get attribute value
* @param attr
* The attribute name
* @return Value of attribute if present and null in other case
*/
private String getAttributeSmart(Element element, String attr)
{
return element.hasAttribute(attr) ? element.getAttribute(attr) : null;
}
/**
* Set attribute value. If value is null the attribute will be removed.
*
* @param element
* The element to set attribute value
* @param attr
* The attribute name
* @param value
* The value of attribute
*/
private void setAttributeSmart(Element element, String attr, String value)
{
if (value == null)
{
element.removeAttribute(attr);
}
else
{
element.setAttribute(attr, value);
}
}
/**
* Get parameters which passed from the configuration file.
*
* @throws RepositoryConfigurationException
*
* @throws RepositoryConfigurationException
*/
private void readParamsFromFile()
{
PropertiesParam props = initParams.getPropertiesParam("artifact.workspace");
if (props == null)
{
throw new IllegalArgumentException("Property parameters 'locations' expected");
}
repoWorkspaceName = props.getProperty("workspace");
rootNodePath = props.getProperty("rootNode");
LOG.info("Workspace from configuration file: " + repoWorkspaceName);
LOG.info("RootNode from configuration file: " + rootNodePath);
}
public List getListErrors()
{
return listErrorPom;
}
}