1   package com.atlassian.maven.plugins.amps.product;
2   
3   import com.atlassian.maven.plugins.amps.MavenGoals;
4   import com.atlassian.maven.plugins.amps.Product;
5   import com.atlassian.maven.plugins.amps.ProductArtifact;
6   import com.atlassian.maven.plugins.amps.util.ConfigFileUtils;
7   
8   import org.apache.commons.io.FileUtils;
9   import org.apache.commons.io.IOUtils;
10  import org.apache.maven.plugin.MojoExecutionException;
11  import org.apache.maven.plugin.logging.Log;
12  import org.apache.maven.project.MavenProject;
13  
14  import java.io.File;
15  import java.io.IOException;
16  import java.io.InputStream;
17  import java.util.*;
18  
19  import static java.lang.String.format;
20  
21  public class JiraProductHandler extends AbstractWebappProductHandler
22  {
23      private final Log log;
24  
25      public JiraProductHandler(final MavenProject project, final MavenGoals goals, Log log)
26      {
27          super(project, goals, new JiraPluginProvider());
28          this.log = log;
29      }
30  
31      public String getId()
32      {
33          return "jira";
34      }
35  
36      @Override
37      public ProductArtifact getArtifact()
38      {
39          return new ProductArtifact("com.atlassian.jira", "atlassian-jira-webapp", "RELEASE");
40      }
41  
42      @Override
43      public ProductArtifact getTestResourcesArtifact()
44      {
45          return new ProductArtifact("com.atlassian.jira.plugins", "jira-plugin-test-resources", "LATEST");
46      }
47  
48      public int getDefaultHttpPort()
49      {
50          return 2990;
51      }
52  
53      protected static File getHsqlDatabaseFile(final File homeDirectory)
54      {
55          return new File(homeDirectory, "database");
56      }
57  
58      @Override
59      public Map<String, String> getSystemProperties(final Product ctx)
60      {
61          return new HashMap<String, String>()
62          {
63              {
64                  final String dburl = System.getProperty("amps.datasource.url", format("jdbc:hsqldb:%s/database", fixSlashes(getHomeDirectory(ctx).getAbsolutePath())));
65                  final String driverClass = System.getProperty("amps.datasource.driver", "org.hsqldb.jdbcDriver");
66                  final String username = System.getProperty("amps.datasource.username", "sa");
67                  final String password = System.getProperty("amps.datasource.password", "");
68                  final String datasourceTypeClass = "javax.sql.DataSource";
69  
70                  final String datasource = format("cargo.datasource.url=%s", dburl);
71                  final String driver = format("cargo.datasource.driver=%s", driverClass);
72                  final String datasourceUsername = format("cargo.datasource.username=%s", username);
73                  final String datasourcePassword = format("cargo.datasource.password=%s", password);
74                  final String datasourceType = "cargo.datasource.type=" + datasourceTypeClass;
75                  final String jndi = "cargo.datasource.jndi=jdbc/JiraDS";
76  
77                  put("jira.home", fixSlashes(getHomeDirectory(ctx).getPath()));
78                  put("cargo.datasource.datasource", format("%s|%s|%s|%s|%s|%s", datasource, driver, datasourceUsername, datasourcePassword, datasourceType, jndi));
79              }
80          };
81      }
82  
83      private static String fixSlashes(final String path)
84      {
85          return path.replaceAll("\\\\", "/");
86      }
87  
88      @Override
89      public File getUserInstalledPluginsDirectory(final File webappDir, final File homeDir)
90      {
91          return new File(new File(homeDir, "plugins"), "installed-plugins");
92      }
93  
94      @Override
95      public List<ProductArtifact> getExtraContainerDependencies()
96      {
97          return Arrays.asList(
98                  new ProductArtifact("hsqldb", "hsqldb", "1.8.0.5"),
99                  new ProductArtifact("jta", "jta", "1.0.1"),
100                 new ProductArtifact("ots-jts", "ots-jts", "1.0"),
101 
102                 // for data source and transaction manager providers
103                 new ProductArtifact("jotm", "jotm", "1.4.3"),
104                 new ProductArtifact("jotm", "jotm-jrmp_stubs", "1.4.3"),
105                 new ProductArtifact("jotm", "jotm-iiop_stubs", "1.4.3"),
106                 new ProductArtifact("jotm", "jonas_timer", "1.4.3"),
107                 new ProductArtifact("jotm", "objectweb-datasource", "1.4.3"),
108                 new ProductArtifact("carol", "carol", "1.5.2"),
109                 new ProductArtifact("carol", "carol-properties", "1.0"),
110                 new ProductArtifact("xapool", "xapool", "1.3.1"),
111                 new ProductArtifact("commons-logging", "commons-logging", "1.1.1")
112         );
113     }
114 
115     @Override
116     public String getBundledPluginPath(Product ctx)
117     {
118         // this location used from 4.1 onwards (inclusive)
119         String bundledPluginPluginsPath = "WEB-INF/classes/atlassian-bundled-plugins.zip";
120 
121     	String[] version = ctx.getVersion().split("-", 2)[0].split("\\.");
122         try
123         {
124             long major = Long.parseLong(version[0]);
125             long minor = Long.parseLong(version[1]);
126 
127             if (major < 4 || major == 4 && minor == 0)
128             {
129                 bundledPluginPluginsPath = "WEB-INF/classes/com/atlassian/jira/plugin/atlassian-bundled-plugins.zip";
130             }
131         }
132         catch (NumberFormatException e)
133         {
134             log.debug(String.format("Unable to parse JIRA version '%s', assuming JIRA 4.1 or newer.", ctx.getVersion()), e);
135         }
136 
137         return bundledPluginPluginsPath;
138     }
139 
140     @Override
141     public void processHomeDirectory(final Product ctx, final File homeDir) throws MojoExecutionException
142     {
143         String contextPath = ctx.getContextPath();
144         if (!contextPath.startsWith("/"))
145         {
146             contextPath = "/" + contextPath;
147         }
148         ConfigFileUtils.replace(new File(homeDir, "database.script"), "@project-dir@", homeDir.getParent());
149         ConfigFileUtils.replace(new File(homeDir, "database.script"), "/jira-home/", "/home/");
150         ConfigFileUtils.replace(new File(homeDir, "database.script"), "@base-url@",
151                 "http://" + ctx.getServer() + ":" + ctx.getHttpPort() + contextPath);
152         createDbConfigXmlIfNecessary(homeDir);
153     }
154 
155     static void createDbConfigXmlIfNecessary(File homeDir) throws MojoExecutionException
156     {
157         File dbConfigXml = new File(homeDir, "dbconfig.xml");
158         if (dbConfigXml.exists())
159         {
160             return;
161         }
162 
163         InputStream templateIn = JiraProductHandler.class.getResourceAsStream("jira-dbconfig-template.xml");
164         if (templateIn == null)
165         {
166             throw new MojoExecutionException("Missing internal resource: jira-dbconfig-template.xml");
167         }
168 
169         try
170         {
171             String template = IOUtils.toString(templateIn, "utf-8");
172 
173             File dbFile = getHsqlDatabaseFile(homeDir);
174             String jdbcUrl = "jdbc:hsqldb:file:" + dbFile.toURI().getPath();
175             String result = template.replace("@jdbc-url@", jdbcUrl);
176             FileUtils.writeStringToFile(dbConfigXml, result, "utf-8");
177         }
178         catch (IOException ioe)
179         {
180             throw new MojoExecutionException("Unable to create dbconfig.xml", ioe);
181         }
182     }
183 
184     @Override
185     public List<ProductArtifact> getDefaultLibPlugins()
186     {
187         return Collections.emptyList();
188     }
189 
190     @Override
191     public List<ProductArtifact> getDefaultBundledPlugins()
192     {
193         return Collections.emptyList();
194     }
195 
196     private static class JiraPluginProvider extends AbstractPluginProvider
197     {
198 
199         @Override
200         protected Collection<ProductArtifact> getSalArtifacts(String salVersion)
201         {
202             return Arrays.asList(
203                 new ProductArtifact("com.atlassian.sal", "sal-api", salVersion),
204                 new ProductArtifact("com.atlassian.sal", "sal-jira-plugin", salVersion));
205         }
206 
207         @Override
208         protected Collection<ProductArtifact> getPdkInstallArtifacts(String pdkInstallVersion)
209         {
210             List<ProductArtifact> plugins = new ArrayList<ProductArtifact>();
211             plugins.addAll(super.getPdkInstallArtifacts(pdkInstallVersion));
212             plugins.add(new ProductArtifact("commons-fileupload", "commons-fileupload", "1.2.1"));
213             return plugins;
214         }
215     }
216 }