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; } }