/xservices/trunk/src/java/net/brutex/xservices/ws/rs/DIMCMInfo.java |
---|
0,0 → 1,80 |
/* |
* 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 javax.ws.rs.DefaultValue; |
import javax.ws.rs.GET; |
import javax.ws.rs.Path; |
import javax.ws.rs.Produces; |
import javax.ws.rs.QueryParam; |
import javax.ws.rs.core.Context; |
import javax.ws.rs.core.HttpHeaders; |
import javax.ws.rs.core.Response; |
import javax.ws.rs.core.UriInfo; |
import org.apache.jcs.access.exception.CacheException; |
import net.brutex.xservices.ws.XServicesFault; |
/** |
* The Dim CM Browsing Rest Service. |
* |
* @author Brian Rosenberger, bru(at)brutex.de |
*/ |
@Path("/") |
@Produces({ "text/xml" }) |
public abstract interface DIMCMInfo { |
public final static String BASE_PATH = "/DIMCMService/"; |
public final static String SERVICE_NAME = "DIMCMInfoService"; |
/** |
* Get the file/ directory listing. |
* |
* @param paramHttpHeaders the param http headers |
* @param uriInfo request url info |
* @param directory The directory to list. |
* @param includeDirectories Whether or not to include directories in the listing. Default is true. |
* @param includeFiles Whether or not to include files in the listing. Default is true. |
* @param depth Include subdirectories down to a given depth. Default is 1. |
* @param search Additional "Glob search pattern" for the file/ directory name. I.e. '*.log' |
* @param itemsPerPage How many items to return with one call. Default is 50. |
* @param page Paging support. Default is 1. |
* @param useCache whether or not to use cache. Defaults to true. |
* @return the FileInfo Set as an XML structure |
* @throws CacheException |
*/ |
@GET |
@Path("getItems/") |
public abstract Response getFiles( |
@Context HttpHeaders paramHttpHeaders, |
@Context UriInfo uriInfo, |
@QueryParam("projSpec") String project, |
@QueryParam("directory") String directory, |
@QueryParam("recursive") @DefaultValue("false") boolean recursive, |
@QueryParam("includeFiles") @DefaultValue("1") boolean includeFiles, |
@QueryParam("depth") @DefaultValue("1") int depth, |
@QueryParam("search") String search, |
@QueryParam("itemsPerPage") @DefaultValue("50") int itemsPerPage, |
@QueryParam("page") @DefaultValue("1") int page, |
@QueryParam("usecache") @DefaultValue("true") boolean useCache) throws CacheException; |
} |
Property changes: |
Added: svn:mime-type |
+text/plain |
\ No newline at end of property |
/xservices/trunk/src/java/net/brutex/xservices/ws/rs/DIMCMInfoImpl.java |
---|
0,0 → 1,371 |
/* |
* 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<ItemType> getItems(RepositoryFolder f, boolean recursive) { |
DimensionsConnection conn = getDIMCMConnection(); |
List<ItemType> result = new ArrayList<>(); |
/* get Items from current folder */ |
/* latest revision only */ |
List<ItemRevision> 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<RepositoryFolder> 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<FileInfoType> 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<Path> 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<FileInfoType> setDirectory(URI baseuri, String dir, |
boolean withDirectories, boolean withFiles, int depth, String search) { |
List<FileInfoType> list = new ArrayList<FileInfoType>(); |
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; |
} |
} |
} |
Property changes: |
Added: svn:mime-type |
+text/plain |
\ No newline at end of property |
/xservices/trunk/src/java/net/brutex/xservices/ws/rs/FileInfo.java |
---|
0,0 → 1,81 |
/* |
* Copyright 2013 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 javax.ws.rs.DefaultValue; |
import javax.ws.rs.GET; |
import javax.ws.rs.Path; |
import javax.ws.rs.Produces; |
import javax.ws.rs.QueryParam; |
import javax.ws.rs.core.Context; |
import javax.ws.rs.core.HttpHeaders; |
import javax.ws.rs.core.Response; |
import javax.ws.rs.core.UriInfo; |
import net.brutex.xservices.ws.XServicesFault; |
/** |
* The FileBrowsing Rest Service. |
* |
* @author Brian Rosenberger, bru(at)brutex.de |
*/ |
@Path("/FileService/") |
@Produces({ "text/xml" }) |
public abstract interface FileInfo { |
public final static String BASE_PATH = "/FileService/"; |
/** |
* Get the file/ directory listing. |
* |
* @param paramHttpHeaders the param http headers |
* @param uriInfo request url info |
* @param directory The directory to list. |
* @param includeDirectories Whether or not to include directories in the listing. Default is true. |
* @param includeFiles Whether or not to include files in the listing. Default is true. |
* @param depth Include subdirectories down to a given depth. Default is 1. |
* @param search Additional "Glob search pattern" for the file/ directory name. I.e. '*.log' |
* @param itemsPerPage How many items to return with one call. Default is 50. |
* @param page Paging support. Default is 1. |
* @param useCache whether or not to use cache. Defaults to true. |
* @return the FileInfo Set as an XML structure |
*/ |
@GET |
@Path("getFiles/") |
public abstract Response getFiles( |
@Context HttpHeaders paramHttpHeaders, |
@Context UriInfo uriInfo, |
@QueryParam("directory") String directory, |
@QueryParam("includeDirectories") @DefaultValue("0") boolean includeDirectories, |
@QueryParam("includeFiles") @DefaultValue("1") boolean includeFiles, |
@QueryParam("depth") @DefaultValue("1") int depth, |
@QueryParam("search") String search, |
@QueryParam("itemsPerPage") @DefaultValue("50") int itemsPerPage, |
@QueryParam("page") @DefaultValue("1") int page, |
@QueryParam("usecache") @DefaultValue("1") boolean useCache); |
@GET |
@Path("getFile/") |
//@Produces("application/octet-stream") |
public abstract Response getFile( |
@Context HttpHeaders paramHttpHeaders, |
@QueryParam("file") String file); |
} |
Property changes: |
Added: svn:mime-type |
+text/plain |
\ No newline at end of property |
/xservices/trunk/src/java/net/brutex/xservices/ws/rs/FileInfoImpl.java |
---|
0,0 → 1,257 |
/* |
* Copyright 2013 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.FileInputStream; |
import java.io.FileOutputStream; |
import java.io.IOException; |
import java.io.OutputStream; |
import java.net.URI; |
import java.nio.file.DirectoryStream; |
import java.nio.file.FileSystems; |
import java.nio.file.FileVisitOption; |
import java.nio.file.FileVisitResult; |
import java.nio.file.Files; |
import java.nio.file.Path; |
import java.nio.file.PathMatcher; |
import java.nio.file.SimpleFileVisitor; |
import java.nio.file.attribute.BasicFileAttributeView; |
import java.nio.file.attribute.BasicFileAttributes; |
import java.util.ArrayList; |
import java.util.EnumSet; |
import java.util.List; |
import java.util.zip.ZipEntry; |
import java.util.zip.ZipOutputStream; |
import javax.ws.rs.NotAuthorizedException; |
import javax.ws.rs.WebApplicationException; |
import javax.ws.rs.core.GenericEntity; |
import javax.ws.rs.core.HttpHeaders; |
import javax.ws.rs.core.MediaType; |
import javax.ws.rs.core.Response; |
import javax.ws.rs.core.StreamingOutput; |
import javax.ws.rs.core.UriInfo; |
import net.brutex.xservices.security.DirectoryPermission; |
import net.brutex.xservices.types.FileInfoType; |
import net.brutex.xservices.util.FileWalker; |
import org.apache.jcs.JCS; |
import org.apache.jcs.access.exception.CacheException; |
import org.apache.log4j.Logger; |
import org.apache.shiro.SecurityUtils; |
import org.apache.shiro.authz.UnauthorizedException; |
/** |
* The Class FileInfoImpl. |
* |
* @author Brian Rosenberger, bru(at)brutex.de |
*/ |
public class FileInfoImpl implements FileInfo { |
Logger logger = Logger.getLogger(FileInfoImpl.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 dir, boolean withDir, boolean withFiles, int level, String search, int count, int page, boolean useCache) |
{ |
isPermitted(dir); |
URI baseuri = URI.create(uriInfo.getBaseUri()+FileInfo.BASE_PATH+"getFile?file="); |
if(dir==null) {dir = "c:/"; System.out.println("No directory specified.");} |
logger.info(String.format("Listing directory '%s'.", dir)); |
if (level <= 0) level = 1; |
if ((!withDir) && (!withFiles)) withFiles = true; |
String cachekey = level + "||" + withFiles + "||" + withDir + "||" + search + "||" + dir; |
try { |
logger.debug(String.format("Hitting cache with cachekey '%s'", cachekey)); |
JCS jcs = JCS.getInstance("FileCache"); |
/*Try to retrieve the file list from the cache*/ |
List<FileInfoType> list = (List<FileInfoType>)jcs.get(cachekey); |
if (list == null || !useCache) { |
list = setDirectory(baseuri, dir, withDir, withFiles, level, search); |
jcs.put(cachekey, list); |
logger.debug("Stored in Cache: " + list.toString()); |
} else { |
logger.debug("Got from Cache: " + list.toString()); |
} |
int fromIndex = 0; |
int toIndex = 0; |
fromIndex = (page - 1) * count; |
toIndex = page * count; |
if (toIndex > list.size()) toIndex = list.size(); |
if (fromIndex > toIndex) fromIndex = toIndex; |
GenericEntity<List<FileInfoType>> sublist = new GenericEntity<List<FileInfoType>>(list.subList(fromIndex, toIndex)) {}; |
logger.info(String.format("Returning items %s to %s from total of %s items in the list.", fromIndex, toIndex, list.size())); |
return Response.ok(sublist).build(); |
} catch (CacheException e) { |
Response.serverError().build(); |
} |
return null; |
} |
/** |
* 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<FileInfoType> 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<Path> 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<FileInfoType> setDirectory(URI baseuri, String dir, boolean withDirectories, boolean withFiles, int depth, String search) |
{ |
List<FileInfoType> list = new ArrayList<FileInfoType>(); |
setDirectory(baseuri, list, new File(dir), withDirectories, withFiles, depth, search); |
return list; |
} |
@Override |
public Response getFile(HttpHeaders paramHttpHeaders, String file) { |
isPermitted(file); |
try { |
Path path = FileSystems.getDefault().getPath(file); |
BasicFileAttributeView basicView = Files.getFileAttributeView(path, BasicFileAttributeView.class); |
BasicFileAttributes basic; |
basic = basicView.readAttributes(); |
//In case this is a directory |
//we zip it and return the zip stream |
if(basic.isDirectory()) return getDirectoryAsZip(path); |
MediaType mime = MediaType.APPLICATION_OCTET_STREAM_TYPE; |
try { |
mime = MediaType.valueOf(Files.probeContentType(path)); |
} catch (IllegalArgumentException | IOException e) { |
//In case we can not find the media type for some reason |
//the default assignment is taken, so we can |
//ignore this error. |
logger.debug(String.format("Could not probe media type for file '%s'. Default is '%s'", path.toString(), mime.getType()), e); |
} |
Response r = Response.ok(path.toFile(), mime).build(); |
String fileName = path.getFileName().toString(); |
if(mime == MediaType.APPLICATION_OCTET_STREAM_TYPE) r.getHeaders().add("Content-Disposition", "attachment; filename=\"" + fileName + "\""); |
return r; |
} catch (IOException e1) { |
// TODO Auto-generated catch block |
logger.error(e1.getMessage(), e1); |
return Response.serverError().build(); |
} |
} |
private Response getDirectoryAsZip(final Path path) { |
StreamingOutput output = new StreamingOutput() { |
@Override |
public void write(OutputStream os) throws IOException, |
WebApplicationException { |
ZipOutputStream zos = new ZipOutputStream(os); |
//read directory content (files only) |
try (DirectoryStream<Path> stream = Files.newDirectoryStream(path)) { |
for (Path file: stream) { |
//skip anything not being a file |
if(! file.toFile().isFile()) continue; |
//ZipEntry |
String filename = file.getFileName().toString(); |
ZipEntry ze = new ZipEntry(filename); |
zos.putNextEntry( ze ); |
//read a file and put it into the output stream |
FileInputStream fis = new FileInputStream(file.toFile()); |
byte[] buffer = new byte[1024]; |
int len; |
while ((len = fis.read(buffer)) > 0) { |
zos.write(buffer, 0, len); |
} |
zos.flush(); |
fis.close(); |
} |
zos.close(); |
} |
} |
}; |
Response r = Response.ok(output, MediaType.APPLICATION_OCTET_STREAM_TYPE).build(); |
String zipname = (path.getFileName()==null) ? "null.zip" : path.getFileName().toString()+".zip"; |
r.getHeaders().add("Content-Disposition", "attachment; filename=\"" + zipname + "\""); |
return r; |
} |
private boolean isPermitted(String dir) { |
if(! SecurityUtils.getSubject().isPermitted( new DirectoryPermission(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; |
} |
} |
Property changes: |
Added: svn:mime-type |
+text/plain |
\ No newline at end of property |
/xservices/trunk/src/java/net/brutex/xservices/ws/rs/ResultType.java |
---|
0,0 → 1,18 |
package net.brutex.xservices.ws.rs; |
import net.brutex.xservices.types.scm.ItemType; |
class ResultType |
{ |
private ItemType result = null; |
ItemType getResult() |
{ |
return this.result; |
} |
void setResult(ItemType result) |
{ |
this.result = result; |
} |
} |
Property changes: |
Added: svn:mime-type |
+text/plain |
\ No newline at end of property |
/xservices/trunk/src/java/net/brutex/xservices/ws/rs/CVSInfo.java |
---|
0,0 → 1,47 |
package net.brutex.xservices.ws.rs; |
import java.io.File; |
import javax.ws.rs.DefaultValue; |
import javax.ws.rs.GET; |
import javax.ws.rs.Path; |
import javax.ws.rs.Produces; |
import javax.ws.rs.QueryParam; |
import javax.ws.rs.core.Context; |
import javax.ws.rs.core.HttpHeaders; |
import javax.ws.rs.core.Response; |
@Path("/CVSService/") |
@Produces({"application/xml", "application/json"}) |
public abstract interface CVSInfo |
{ |
public static final String WS_OPERATION_GETREPOSITORYFILES = "getRepositoryFiles"; |
public static final String WS_OPERATION_GETMODULES = "getModules"; |
public static final String WS_OPERATION_GETTAGS = "getTags"; |
public static final String WS_OPERATION_GETFILECONTENT = "getFileContent"; |
public static final String WS_OPERATION_SEARCHFILECONTENT = "searchFileContent"; |
@GET |
@Path("getRepositoryFiles") |
public abstract Response getRepositoryFiles(@Context HttpHeaders paramHttpHeaders, @QueryParam("config") File paramFile, @QueryParam("modules") @DefaultValue("") String paramString, @QueryParam("recursive") @DefaultValue("false") boolean paramBoolean1, @QueryParam("showRevisions") @DefaultValue("false") boolean paramBoolean2, @QueryParam("forceNoCache") @DefaultValue("false") boolean paramBoolean3); |
@GET |
@Path("getModules") |
public abstract Response getModules(@Context HttpHeaders paramHttpHeaders, @QueryParam("config") File paramFile, @QueryParam("forceNoCache") @DefaultValue("false") boolean paramBoolean); |
@GET |
@Path("getTags") |
public abstract Response getTags(@Context HttpHeaders paramHttpHeaders, @QueryParam("config") File paramFile, @QueryParam("withFiles") @DefaultValue("false") boolean paramBoolean); |
@GET |
@Path("getFileContent") |
public abstract Response getFileContent(@Context HttpHeaders paramHttpHeaders, @QueryParam("config") File paramFile, @QueryParam("file") String paramString, @QueryParam("forceNoCache") @DefaultValue("false") boolean paramBoolean); |
@GET |
@Path("searchFileContent") |
public abstract Response searchFileContent(@Context HttpHeaders paramHttpHeaders, @QueryParam("config") File paramFile, @QueryParam("file_regexp") String paramString1, @QueryParam("content_regexp") String paramString2, @QueryParam("forceNoCache") @DefaultValue("false") boolean paramBoolean); |
} |
/* Location: C:\Users\brosenberger\Documents\My Box Files\XBridgeNG-download\XServices-20130131 - Kopie\WEB-INF\classes\net.zip |
* Qualified Name: net.brutex.xservices.ws.rs.CVSInfo |
* JD-Core Version: 0.6.2 |
*/ |
Property changes: |
Added: svn:mime-type |
+text/plain |
\ No newline at end of property |
/xservices/trunk/src/java/net/brutex/xservices/ws/rs/CVSInfoImpl.java |
---|
0,0 → 1,377 |
package net.brutex.xservices.ws.rs; |
import java.io.ByteArrayOutputStream; |
import java.io.File; |
import java.io.FileReader; |
import java.io.IOException; |
import java.io.PrintStream; |
import java.net.URI; |
import java.util.List; |
import java.util.StringTokenizer; |
import javax.ws.rs.core.HttpHeaders; |
import javax.ws.rs.core.Response; |
import javax.ws.rs.core.Response.ResponseBuilder; |
import net.brutex.xservices.types.scm.AttributeType; |
import net.brutex.xservices.types.scm.ItemListType; |
import net.brutex.xservices.types.scm.ItemType; |
import net.brutex.xservices.types.scm.ModuleListType; |
import net.brutex.xservices.types.scm.ModuleType; |
import net.brutex.xservices.types.scm.ObjectFactory; |
import net.brutex.xservices.types.scm.RevisionType; |
import net.brutex.xservices.types.scm.TagListType; |
import net.brutex.xservices.types.scmfindings.FindingsListType; |
import net.brutex.xservices.util.BasicCVSListener; |
import net.brutex.xservices.util.CVSClient; |
import net.brutex.xservices.util.CVSRoot; |
import org.apache.commons.configuration.ConfigurationException; |
import org.apache.jcs.JCS; |
import org.apache.jcs.access.exception.CacheException; |
import org.apache.log4j.Logger; |
import org.netbeans.lib.cvsclient.Client; |
import org.netbeans.lib.cvsclient.command.CommandAbortedException; |
import org.netbeans.lib.cvsclient.command.CommandException; |
import org.netbeans.lib.cvsclient.command.FileInfoContainer; |
import org.netbeans.lib.cvsclient.command.PipedFileInformation; |
import org.netbeans.lib.cvsclient.command.checkout.CheckoutCommand; |
import org.netbeans.lib.cvsclient.command.checkout.ModuleListInformation; |
import org.netbeans.lib.cvsclient.command.log.LogInformation; |
import org.netbeans.lib.cvsclient.command.log.LogInformation.Revision; |
import org.netbeans.lib.cvsclient.command.log.RlogCommand; |
import org.netbeans.lib.cvsclient.connection.AuthenticationException; |
import org.netbeans.lib.cvsclient.event.EventManager; |
import org.netbeans.lib.cvsclient.event.FileInfoEvent; |
public class CVSInfoImpl implements CVSInfo { |
final Logger logger = Logger.getLogger(CVSInfoImpl.class); |
final ObjectFactory FACTORY = new ObjectFactory(); |
final ItemListType list = this.FACTORY.createItemListType(); |
public Response getRepositoryFiles(HttpHeaders h, File f, String modules, |
boolean isRecursive, boolean showRevisions, boolean forceNoCache) { |
String cachekey = "getFiles" + f.toURI().toString(); |
this.logger.debug("forceNoCache=" + forceNoCache); |
ItemListType cacheresult = (ItemListType) getCacheInstance().get( |
cachekey); |
if ((!forceNoCache) && (cacheresult != null)) { |
return Response.ok(cacheresult).build(); |
} |
Client client; |
try { |
final CVSClient cvsclient = new CVSClient(f); |
client = cvsclient.client; |
client.getEventManager().addCVSListener(new BasicCVSListener() { |
public void fileInfoGenerated(FileInfoEvent arg0) { |
LogInformation info = (LogInformation) arg0 |
.getInfoContainer(); |
String repoPath = cvsclient.client.getRepository(); |
ItemType cvsfile = CVSInfoImpl.this.FACTORY |
.createItemType(); |
cvsfile.setIsLeaf(true); |
cvsfile.setIsBinary(false); |
cvsfile.setFullname(info.getRepositoryFilename().substring( |
repoPath.length() + 2, |
info.getRepositoryFilename().length() - 2)); |
cvsfile.setRemotename(info.getRepositoryFilename()); |
cvsfile.setRemotefullname(info.getRepositoryFilename()); |
RevisionType revision = CVSInfoImpl.this.FACTORY |
.createRevisionType(); |
revision.setRevision(info.getHeadRevision()); |
revision.setComment(info.getDescription()); |
cvsfile.setTipRevision(revision); |
for (LogInformation.Revision r : info.getRevisionList()) { |
revision = CVSInfoImpl.this.FACTORY |
.createRevisionType(); |
revision.setRevision(r.getNumber()); |
revision.setComment(r.getMessage()); |
cvsfile.getRevisions().add(revision); |
} |
cvsfile.getAttributes().add( |
CVSInfoImpl.this.getAttribute("TOTALREVISIONS", |
info.getTotalRevisions())); |
cvsfile.getAttributes().add( |
CVSInfoImpl.this.getAttribute("BRANCH", |
info.getBranch())); |
cvsfile.getAttributes().add( |
CVSInfoImpl.this.getAttribute( |
"KEYWORDSUBSTITUTION", |
info.getKeywordSubstitution())); |
cvsfile.getAttributes().add( |
CVSInfoImpl.this.getAttribute("LOCKS", |
info.getLocks())); |
cvsfile.getAttributes().add( |
CVSInfoImpl.this.getAttribute("SELECTEDREVISIONS", |
info.getSelectedRevisions())); |
cvsfile.setROOT(cvsclient.getRoot().host + "@" |
+ cvsclient.getRoot().repository); |
CVSInfoImpl.this.list.getItems().add(cvsfile); |
String key = CVSClient.generateID(cvsfile); |
try { |
CVSInfoImpl.this.getCacheInstance().put(key, cvsfile); |
} catch (CacheException e) { |
CVSInfoImpl.this.logger.error("Could not cache item '" |
+ key + "'", e); |
} |
} |
}); |
RlogCommand rlog = new RlogCommand(); |
StringTokenizer tk = new StringTokenizer(modules, ","); |
while (tk.hasMoreTokens()) { |
rlog.setModule(tk.nextToken()); |
} |
if (rlog.getModules().length == 0) { |
rlog.setModule(""); |
} |
rlog.setDefaultBranch(false); |
rlog.setNoTags(false); |
rlog.setHeaderAndDescOnly(false); |
rlog.setRecursive(isRecursive); |
this.logger.info("Executing CVS command '" + rlog.getCVSCommand() |
+ "' against '" + cvsclient.getRoot().host + "@" |
+ cvsclient.getRoot().repository + "'"); |
client.executeCommand(rlog, cvsclient.getGlobalOptions()); |
getCacheInstance().put(cachekey, this.list); |
} catch (ConfigurationException e) { |
this.logger.error("CVS Configuration File '" + f.getAbsolutePath() |
+ f.getName() + "'not found.", e); |
} catch (CommandAbortedException e) { |
e.printStackTrace(); |
} catch (AuthenticationException e) { |
e.printStackTrace(); |
} catch (CommandException e) { |
e.printStackTrace(); |
} catch (CacheException e) { |
e.printStackTrace(); |
} |
if (!showRevisions) { |
for (ItemType t : this.list.getItems()) { |
t.getRevisions().clear(); |
} |
} |
return Response.ok(this.list).build(); |
} |
public Response getModules(HttpHeaders h, File f, boolean forceNoCache) { |
String cachekey = "Modules" + f.toURI().toString(); |
this.logger.debug("forceNoCache=" + forceNoCache); |
ModuleListType response = (ModuleListType) getCacheInstance().get( |
cachekey); |
if ((!forceNoCache) && (response != null)) { |
return Response.ok(response).build(); |
} |
try { |
CVSClient cvsclient = new CVSClient(f); |
Client client = cvsclient.client; |
final ModuleListType list = this.FACTORY.createModuleListType(); |
client.getEventManager().addCVSListener(new BasicCVSListener() { |
public void fileInfoGenerated(FileInfoEvent e) { |
ModuleListInformation info = (ModuleListInformation) e |
.getInfoContainer(); |
ModuleType module = CVSInfoImpl.this.FACTORY |
.createModuleType(); |
module.setName(info.getModuleName()); |
module.setStatus(info.getModuleStatus()); |
module.setPath(info.getPaths()); |
module.setType(info.getType()); |
list.getModules().add(module); |
} |
}); |
CheckoutCommand co = new CheckoutCommand(); |
co.setShowModulesWithStatus(true); |
this.logger.info("Executing CVS command '" + co.getCVSCommand() |
+ "' against '" + cvsclient.getRoot().host + "@" |
+ cvsclient.getRoot().repository + "'"); |
client.executeCommand(co, cvsclient.getGlobalOptions()); |
if (list.getModules().size() == 0) { |
this.logger.warn("Repository '" |
+ cvsclient.getRoot().repository |
+ "' does not have modules"); |
} |
getCacheInstance().put(cachekey, list); |
return Response.ok(list).build(); |
} catch (Exception e) { |
e.printStackTrace(); |
} |
return Response.serverError().build(); |
} |
public Response getTags(HttpHeaders h, File f, boolean withFiles) { |
String cachekey = f.toURI().toString() + ":taglist"; |
this.logger.debug("Retrieving Tags from cache using key '" + cachekey |
+ "'"); |
TagListType tags = (TagListType) getCacheInstance().get(cachekey); |
if (tags != null) { |
this.logger.debug("Delivering Tags from cache."); |
return Response.ok(tags).build(); |
} |
this.logger.warn("Taglist not found in cache."); |
return Response.noContent().build(); |
} |
public Response getFileContent(HttpHeaders h, File f, String filestring, |
boolean forceNoCache) { |
final ItemType result = this.FACTORY.createItemType(); |
final String cachekey = f.toURI().toString() + ":" + filestring |
+ ":content"; |
ItemListType list = null; |
if (!forceNoCache) { |
this.logger.debug("Retrieving file content from cache using key '" |
+ cachekey + "'"); |
list = (ItemListType) getCacheInstance().get(cachekey); |
} |
if (list != null) { |
this.logger.debug("Delivering file content from cache."); |
return Response.ok(list).build(); |
} |
this.logger.warn("File content not found in cache."); |
list = this.FACTORY.createItemListType(); |
try { |
CVSClient cvsclient = new CVSClient(f); |
Client client = cvsclient.getClient(); |
CheckoutCommand checkout = new CheckoutCommand(); |
BasicCVSListener listener = new BasicCVSListener() { |
public void fileInfoGenerated(FileInfoEvent arg0) { |
System.out.println(arg0.getInfoContainer().getFile() |
.toURI().toString()); |
PipedFileInformation info = (PipedFileInformation) arg0 |
.getInfoContainer(); |
result.setName(info.getFile().getName()); |
try { |
boolean isBinary = false; |
result.setIsBinary(isBinary); |
result.setRemotename(info.getRepositoryFileName()); |
RevisionType revision = CVSInfoImpl.this.FACTORY |
.createRevisionType(); |
revision.setRevision(info.getRepositoryRevision()); |
revision.setComment(""); |
if (!isBinary) { |
FileReader fin = new FileReader(info.getTempFile()); |
ByteArrayOutputStream bout = new ByteArrayOutputStream(); |
StringBuffer sbuf = new StringBuffer(); |
int c; |
while ((c = fin.read()) != -1) { |
bout.write(c); |
sbuf.append((char) c); |
} |
result.setData(bout.toByteArray()); |
result.setContent(sbuf.toString()); |
} |
} catch (IOException e2) { |
e2.printStackTrace(); |
} catch (NullPointerException ne) { |
ne.printStackTrace(); |
} |
String key = CVSClient.generateID(result); |
try { |
CVSInfoImpl.this.getCacheInstance().put(cachekey, |
result); |
} catch (CacheException e1) { |
e1.printStackTrace(); |
} |
} |
}; |
client.getEventManager().addCVSListener(listener); |
checkout.setModule(filestring); |
checkout.setPipeToOutput(true); |
this.logger.info("Execute CVS command '" + checkout.getCVSCommand() |
+ "' against '" + cvsclient.getRoot().host + "@" |
+ cvsclient.getRoot().repository + "'"); |
client.executeCommand(checkout, cvsclient.getGlobalOptions()); |
} catch (CommandAbortedException e) { |
e.printStackTrace(); |
} catch (ConfigurationException e) { |
e.printStackTrace(); |
} catch (AuthenticationException e) { |
e.printStackTrace(); |
} catch (CommandException e) { |
e.printStackTrace(); |
} |
if (result.getContent() != null) { |
return Response.ok(result).build(); |
} |
return Response.noContent().build(); |
} |
public JCS getCacheInstance() { |
JCS jcs = null; |
String cacheinstance = "CVSCache"; |
try { |
this.logger.trace("Getting cache instance named 'CVSCache'"); |
jcs = JCS.getInstance("CVSCache"); |
} catch (CacheException e) { |
this.logger.error("Failed to get cache instance", e); |
e.printStackTrace(); |
} |
return jcs; |
} |
public Response searchFileContent(HttpHeaders h, File f, |
String file_regexp, String content_regexp, boolean forceNoCache) { |
try { |
CVSClient client = new CVSClient(f); |
String cvsroot = client.getRoot().host + "@" |
+ client.getRoot().repository; |
String cachestring = "FINDINGS-" + cvsroot; |
this.logger |
.debug("Fetch searchFileContent response from cache using cachekey '" |
+ cachestring + "'"); |
FindingsListType result = (FindingsListType) getCacheInstance() |
.get(cachestring); |
if (result != null) |
this.logger.debug("Found object for key '" + cachestring |
+ "' in cache."); |
else { |
this.logger.debug("Found no object for key '" + cachestring |
+ "' in cache."); |
} |
if (result != null) |
return Response.ok(result).build(); |
} catch (CommandAbortedException e) { |
e.printStackTrace(); |
} catch (ConfigurationException e) { |
e.printStackTrace(); |
} catch (AuthenticationException e) { |
e.printStackTrace(); |
} |
return Response.noContent().build(); |
} |
private AttributeType getAttribute(String name, String value) { |
AttributeType attribute = this.FACTORY.createAttributeType(); |
attribute.setName(name); |
attribute.setValue(value); |
return attribute; |
} |
} |
Property changes: |
Added: svn:mime-type |
+text/plain |
\ No newline at end of property |
/xservices/trunk/src/java/net/brutex/xservices/ws/rs/FileListType.java |
---|
0,0 → 1,21 |
package net.brutex.xservices.ws.rs; |
import javax.xml.bind.annotation.XmlElement; |
import javax.xml.bind.annotation.XmlRootElement; |
@XmlRootElement(name="FileList") |
public class FileListType |
{ |
@XmlElement |
public String name; |
public FileListType() |
{ |
} |
public FileListType(String name) |
{ |
this.name = name; |
} |
} |
Property changes: |
Added: svn:mime-type |
+text/plain |
\ No newline at end of property |