/* * Copyright 2014 Brian Rosenberger (Brutex Network) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package net.brutex.xservices.ws.rs; import java.io.File; import java.io.IOException; import java.net.MalformedURLException; import java.net.URI; import java.net.URL; import java.nio.file.FileVisitOption; import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; import java.util.EnumSet; import java.util.List; import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.Response; import javax.ws.rs.core.UriInfo; import net.brutex.xservices.cmtypes.ItemType; import net.brutex.xservices.cmtypes.ItemTypeList; import net.brutex.xservices.types.FileInfoType; import net.brutex.xservices.util.FileWalker; import org.apache.commons.configuration.ConfigurationException; import org.apache.commons.configuration.PropertiesConfiguration; import org.apache.jcs.JCS; import org.apache.jcs.access.exception.CacheException; import org.apache.log4j.Logger; /* * The Serena Dimensions CM Java API is required for these imports. * The API is not included in this package due to copyright reasons, * please get Dimensions CM from Serena Software Inc., Evaluation versions * are available from http://www.serena.com * * required Jars: * serena.darius-14.1.jar * serena.dmclient-14.1.jar * serena.dmfile-14.1.jar * serena.dmnet-14.1.jar * serena.dmtpi-14.1.jar * */ import com.serena.dmclient.api.BulkOperator; import com.serena.dmclient.api.DimensionsConnection; import com.serena.dmclient.api.DimensionsConnectionDetails; import com.serena.dmclient.api.DimensionsConnectionManager; import com.serena.dmclient.api.ItemRevision; import com.serena.dmclient.api.Project; import com.serena.dmclient.api.RepositoryFolder; import com.serena.dmclient.api.SystemAttributes; /** * The Class FileInfoImpl. * * @author Brian Rosenberger, bru(at)brutex.de */ public class DIMCMInfoImpl implements DIMCMInfo { Logger logger = Logger.getLogger(DIMCMInfoImpl.class); /* * (non-Javadoc) * * @see * net.brutex.xservices.ws.rs.FileInfo#getFiles(javax.ws.rs.core.HttpHeaders * , java.lang.String, boolean, boolean, int, java.lang.String, int, int) */ public Response getFiles(HttpHeaders h, UriInfo uriInfo, String projSpec, String directory, boolean recursive, boolean withFiles, int level, String search, int count, int page, boolean useCache) throws CacheException { /* * try to hit cache first */ JCS cache = JCS.getInstance("DIMCM"); String cachekey = projSpec + directory + String.valueOf(recursive); if(useCache) { ItemTypeList cacheresult = (ItemTypeList) cache.get(cachekey); if(cacheresult != null) return Response.ok(cacheresult).build(); } //Reject when project has not the form "PRODUCT:PROJECT" if(! projSpec.contains(":")) return Response.noContent().build(); Project project = getDIMCMConnection().getObjectFactory().getProject(projSpec); RepositoryFolder folder = null; if (directory == null) { folder = project.getRootFolder(); } else { while(directory.startsWith("/") || directory.startsWith("\\")) { directory = directory.substring(1); } if(directory.equals("")) { folder = project.getRootFolder(); } else { folder = project.findRepositoryFolderByPath(directory); } } ItemTypeList resultlist = new ItemTypeList(); resultlist.list = getItems(folder, recursive); if(cache!=null) cache.put(cachekey, resultlist); //does this help? DimensionsConnectionManager.unregisterThreadConnection(); return Response.ok(resultlist).build(); } List getItems(RepositoryFolder f, boolean recursive) { DimensionsConnection conn = getDIMCMConnection(); List result = new ArrayList<>(); /* get Items from current folder */ /* latest revision only */ List revisions = f.getLatestItemRevisions(); int[] attr = { SystemAttributes.FULL_PATH_NAME, SystemAttributes.ITEMFILE_DIR, SystemAttributes.ITEMFILE_FILENAME, SystemAttributes.ITEMFILE_DIR, SystemAttributes.OBJECT_SPEC, SystemAttributes.OBJECT_ID, SystemAttributes.OBJECT_SPEC_UID, SystemAttributes.OBJECT_UID, SystemAttributes.CREATION_DATE, SystemAttributes.CREATION_USER, SystemAttributes.ITEM_FORMAT, SystemAttributes.LAST_UPDATED_DATE, SystemAttributes.LAST_UPDATED_USER }; BulkOperator bulk = conn.getObjectFactory().getBulkOperator(revisions); bulk.queryAttribute(attr); // Copy into JAXB object for (ItemRevision r : revisions) { ItemType item = new ItemType(); item.setLongFilename((String) r .getAttribute(SystemAttributes.FULL_PATH_NAME)); item.setDirName((String) r .getAttribute(SystemAttributes.ITEMFILE_DIR)); item.setShortFilename((String) r .getAttribute(SystemAttributes.ITEMFILE_FILENAME)); item.setObject_id((String) r .getAttribute(SystemAttributes.OBJECT_ID)); item.setObject_uid((String.valueOf(r .getAttribute(SystemAttributes.OBJECT_UID)))); item.setObject_spec((String) r .getAttribute(SystemAttributes.OBJECT_SPEC)); item.setObject_spec_uid(String.valueOf(r .getAttribute(SystemAttributes.OBJECT_SPEC_UID))); item.setObject_spec_uid(String.valueOf(r .getAttribute(SystemAttributes.OBJECT_SPEC_UID))); item.setCreatedDate(String.valueOf(r .getAttribute(SystemAttributes.CREATION_DATE))); item.setCreatedUser(String.valueOf(r .getAttribute(SystemAttributes.CREATION_USER))); item.setItemFormat(String.valueOf(r .getAttribute(SystemAttributes.ITEM_FORMAT))); item.setUpdatedDate(String.valueOf(r .getAttribute(SystemAttributes.LAST_UPDATED_DATE))); item.setUpdatedUser(String.valueOf(r .getAttribute(SystemAttributes.LAST_UPDATED_USER))); try { item.setUrl(new URL(getBaseURL() + "?jsp=api&command=openi&object_id=" + item.getObject_spec() + "&DB_CONN=" + conn.getConnectionDetails().getDbConn() + "&DB_NAME=" + conn.getConnectionDetails().getDbName())); } catch (MalformedURLException e) { // TODO Auto-generated catch block e.printStackTrace(); } result.add(item); } /* * for recursive add other folders */ if(recursive) { List folders = f.getAllChildFolders(); for(RepositoryFolder ff : folders) { result.addAll(getItems(ff, false)); } } return result; } /** * Sets the directory. * * @param list * the list * @param dir * the dir * @param withDirectories * the with directories * @param withFiles * the with files * @param depth * the depth * @param search * the search */ private void setDirectory(final URI baseuri, final List list, File dir, boolean withDirectories, boolean withFiles, final int depth, String search) { if (depth <= 0) return; if (search == null || search.equals("")) { search = "*"; logger.info("No search pattern supplied, using default '*'."); } FileWalker finder = new FileWalker(search); try { Files.walkFileTree(dir.toPath(), EnumSet.of(FileVisitOption.FOLLOW_LINKS), depth, finder); logger.info("FileWalker returned '" + finder.getCount() + "' hits. '" + finder.getTotal() + "' files have been scanned."); List result = finder.getResult(); for (Path f : result) { if (!withDirectories) { if (f.toFile().isDirectory()) continue; } if (!withFiles) { if (f.toFile().isFile()) continue; } list.add(new FileInfoType(f, baseuri)); } } catch (IOException e2) { logger.error(e2.getMessage(), e2); ; } } /** * Sets the directory. * * @param dir * the dir * @param withDirectories * the with directories * @param withFiles * the with files * @param depth * the depth * @param search * the search * @return the list */ private List setDirectory(URI baseuri, String dir, boolean withDirectories, boolean withFiles, int depth, String search) { List list = new ArrayList(); setDirectory(baseuri, list, new File(dir), withDirectories, withFiles, depth, search); return list; } private boolean isPermitted(String dir) { /* * * logger.warn(String.format( * "User '%s' does not have permission to access '%s'." * ,SecurityUtils.getSubject().getPrincipal(), dir )); throw new * NotAuthorizedException(new * UnauthorizedException("User does not have permission to access "+ * dir)); } */ return true; } // http://stackoverflow.com/questions/3758606/how-to-convert-byte-size-into-human-readable-format-in-java private static String humanReadableByteCount(long bytes, boolean si) { int unit = si ? 1000 : 1024; if (bytes < unit) return bytes + " B"; int exp = (int) (Math.log(bytes) / Math.log(unit)); String pre = (si ? "kMGTPE" : "KMGTPE").charAt(exp - 1) + (si ? "" : "i"); return String.format("%.1f %sB", bytes / Math.pow(unit, exp), pre); } private DimensionsConnection getDIMCMConnection() { /* * Do we have a registered connection already? */ DimensionsConnection conn = null; try { conn = DimensionsConnectionManager.getThreadConnection(); if (conn != null) return conn; } catch (Exception e) { logger.error(e.getMessage()); } /* * Create a new connection from property file */ PropertiesConfiguration props; try { props = new PropertiesConfiguration(this.getClass() .getClassLoader().getResource("/../dimcm.properties")); } catch (ConfigurationException e) { e.printStackTrace(); return null; } DimensionsConnectionDetails details = new DimensionsConnectionDetails(); details.setUsername(props.getString("user")); details.setPassword(props.getString("password")); details.setDbName(props.getString("dbname")); details.setDbConn(props.getString("dbconn")); details.setServer(props.getString("server")); conn = DimensionsConnectionManager.getConnection(details); DimensionsConnectionManager.registerThreadConnection(conn); return conn; } private String getBaseURL() { final String CACHE_BASEURL = "DIMCM.conf.baseurl"; try { JCS cache = JCS.getInstance("DIMCM"); String baseurl = (String) cache.get(CACHE_BASEURL); if(baseurl != null) return baseurl; PropertiesConfiguration props = new PropertiesConfiguration(this.getClass().getClassLoader().getResource("/../dimcm.properties")); baseurl = props.getString("baseurl"); cache.put(CACHE_BASEURL, baseurl); return baseurl; } catch (CacheException e1) { // TODO Auto-generated catch block e1.printStackTrace(); return null; } catch (ConfigurationException e) { e.printStackTrace(); return null; } } }