/* * HeadsUp Agile * Copyright 2009-2013 Heads Up Development Ltd. * * 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 Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.headsupdev.agile.app.files; import org.headsupdev.agile.api.service.ScmService; import org.headsupdev.agile.app.files.event.FileChangeSetEvent; import org.headsupdev.agile.app.files.permission.FileListPermission; import org.headsupdev.agile.app.files.permission.FileViewPermission; import org.headsupdev.agile.storage.HibernateStorage; import org.headsupdev.agile.storage.files.File; import org.headsupdev.agile.web.WebApplication; import org.headsupdev.agile.storage.ScmChange; import org.headsupdev.agile.api.*; import org.hibernate.Session; import org.hibernate.Query; import org.osgi.framework.BundleContext; import java.util.*; /** * The files application allows users to browse the checked out files. * * @author Andrew Williams * @version $Id$ * @since 1.0 */ public class BrowseApplication extends WebApplication { public static final String ID = "files"; static transient BrowseScmUpdater updater = new BrowseScmUpdater(); public static final ConfigurationItem CONFIGURATION_UPDATE_DELAY = new ConfigurationItem( "update.delay", 15, "Number of minutes between checking for updated files", "If your source control is on a remote server or public repository leave this as 15 minutes." + "If the files are on the same server you can reduce this value to check more often." ); protected List<ConfigurationItem> globalItems = new LinkedList<ConfigurationItem>(); List<MenuLink> links; List<String> eventTypes; public BrowseApplication() { links = new LinkedList<MenuLink>(); links.add( new SimpleMenuLink( "update" ) ); eventTypes = new LinkedList<String>(); eventTypes.add( "filechangeset" ); updater.setApplication( this ); Manager.getInstance().addProjectListener( updater ); } @Override public void start( BundleContext bc ) { super.start( bc ); Dictionary props = new Properties(); bc.registerService( ScmService.class.getName(), new BrowseScmService(), props ); globalItems.add( CONFIGURATION_UPDATE_DELAY ); } public static BrowseScmUpdater getUpdater() { return updater; } public String getName() { return "Files"; } public String getApplicationId() { return ID; } public String getDescription() { return "The " + Manager.getStorageInstance().getGlobalConfiguration().getProductName() + " scm browse application"; } public List<MenuLink> getLinks( Project project ) { return links; } public List<String> getEventTypes() { return eventTypes; } @Override public Class<? extends Page>[] getPages() { return new Class[] { Browse.class, BrowseChange.class, BrowseFile.class, BrowseHistory.class, Update.class }; } @Override public Class<? extends Page> getHomePage() { return Browse.class; } @Override public Permission[] getPermissions() { return new Permission[] { new FileListPermission(), new FileViewPermission() }; } @Override public LinkProvider[] getLinkProviders() { return new LinkProvider[]{ new ChangeLinkProvider(), new ChangeLogLinkProvider(), new FileLinkProvider() }; } @Override public void stop( BundleContext bc ) throws Exception { super.stop( bc ); updater.stop(); } @Override public List<ConfigurationItem> getConfigurationItems() { return globalItems; } public List<File> getProjectFiles( Project project ) { Session session = ( (HibernateStorage) Manager.getStorageInstance() ).getHibernateSession(); Query q = session.createQuery( "from File f where name.project = :project" ); q.setEntity( "project", project ); List<File> files = q.list(); return files; } public Map<String, File> getProjectFileMap( Project project ) { List<File> files = getProjectFiles( project ); Map<String, File> ret = new HashMap<String, File>(); for ( File file : files ) { ret.put( file.getName(), file ); } return ret; } public static boolean getFileExists( Project project, String fileName ) { Session session = ( (HibernateStorage) Manager.getStorageInstance() ).getHibernateSession(); Query q = session.createQuery( "select count(*) from File f where f.name.project = :project and f.name.name = :name" ); q.setEntity( "project", project ); q.setString( "name", fileName ); return ( (Long) q.uniqueResult() ) > 0; } public static List<ScmChange> getChanges( Project project, String path ) { Session session = ( (HibernateStorage) Manager.getStorageInstance() ).getHibernateSession(); String prefix = ""; java.io.File searchDir = Manager.getStorageInstance().getWorkingDirectory( project ); while ( project.getParent() != null ) { prefix = searchDir.getName() + java.io.File.separatorChar + prefix; project = project.getParent(); searchDir = searchDir.getParentFile(); } Query q = session.createQuery( "from ScmChange c where c.set.id.project = :project and name = :path order by c.set.date desc" ); q.setEntity( "project", project ); q.setString( "path", prefix + path ); return q.list(); } public static boolean getChangeSetExists( Project project, String changeId ) { Session session = ( (HibernateStorage) Manager.getStorageInstance() ).getHibernateSession(); Query q = session.createQuery( "select count(*) from ScmChangeSet s where s.id.project = :project and s.revision = :rev" ); q.setEntity( "project", project ); q.setString( "rev", changeId ); return ( (Long) q.uniqueResult() ) > 0; } public static boolean getChangeExists( Project project, String changeId ) { Session session = ( (HibernateStorage) Manager.getStorageInstance() ).getHibernateSession(); // TODO should we check name? Query q = session.createQuery( "select count(*) from ScmChange c where c.set.id.project = :project and c.revision = :rev" ); q.setEntity( "project", project ); q.setString( "rev", changeId ); return ( (Long) q.uniqueResult() ) > 0; } public Class[] getPersistantClasses() { return new Class[] { FileChangeSetEvent.class }; } }