DBVIEW
|
00001 /* 00002 DbView - Graph Visualization 00003 Copyright (C) 2012 Denis BEURIVE 00004 00005 This program is free software: you can redistribute it and/or modify 00006 it under the terms of the GNU General Public License as published by 00007 the Free Software Foundation, either version 3 of the License, or 00008 (at your option) any later version. 00009 00010 This program is distributed in the hope that it will be useful, 00011 but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 GNU General Public License for more details. 00014 00015 You should have received a copy of the GNU General Public License 00016 along with this program. If not, see <http://www.gnu.org/licenses/>. 00017 */ 00018 00019 package org.dbview.input_addons; 00020 00021 import org.jdom.Element; 00022 import org.jdom.Document; 00023 import org.jdom.output.XMLOutputter; 00024 import java.net.URISyntaxException; 00025 import org.jdom.input.SAXBuilder; 00026 import java.io.File; 00027 import org.dbview.conf.*; 00028 import org.dbview.utils.*; 00029 import java.net.URL; 00030 import java.io.FileWriter; 00031 import org.jdom.xpath.XPath; 00032 import org.jdom.JDOMException; 00033 import org.jdom.Attribute; 00034 import java.util.ArrayList; 00035 import java.util.List; 00036 00037 /** 00038 * <p>This class implements the profile's repository.</p> 00039 * <p>A profile is a set of value used by input add-ons to connect to their associated data source (Mysql...).</p> 00040 * @author Denis BEURIVE 00041 */ 00042 public class ProfilesRepository 00043 { 00044 /** 00045 * XML representation of the list of profiles. 00046 */ 00047 private static Document __profiles = null; 00048 00049 /** 00050 * File that contains the XML description of the list of profiles. 00051 */ 00052 private static File __repository = null; 00053 00054 /** 00055 * Initialize the repository. 00056 * @throws Exception 00057 */ 00058 public static void init() throws Exception 00059 { 00060 if (null != ProfilesRepository.__profiles) { return; } 00061 // { throw new Exception("Unexpected error : The profile repository has already been initialized. It should not be initialized twice."); } 00062 00063 // Build the path to the repository. 00064 ProfilesRepository.__initFile(); 00065 00066 // Shall we create an empty repository? 00067 if (! ProfilesRepository.__repository.exists()) 00068 { 00069 Element root = new Element("profiles"); 00070 root.setAttribute("created", org.dbview.utils.Date.now()); 00071 Document doc = new Document(root); 00072 ProfilesRepository.__setUpdateDateTimeToNow(doc); 00073 ProfilesRepository.__write(doc); 00074 } 00075 00076 // Load the repository. 00077 if (! ProfilesRepository.__repository .isFile()) { throw new Exception("Unexpected error : The entry that represents the profiles' repository \"" + ProfilesRepository.__repository.getPath() + "\" is not a regular file!"); } 00078 if (! ProfilesRepository.__repository .canRead()) { throw new Exception("Unexpected error : The entry that represents the profiles' repository \"" + ProfilesRepository.__repository.getPath() + "\" is not readable!"); } 00079 SAXBuilder builder = new SAXBuilder(); 00080 ProfilesRepository.__profiles = builder.build(ProfilesRepository.__repository); 00081 } 00082 00083 /** 00084 * Add a new profile to the repository. 00085 * @param in_profile Profile to add. 00086 * @throws ProfilesRepositoryException 00087 * @throws Exception 00088 */ 00089 public static void add(AbstractConfiguration in_profile) throws ProfilesRepositoryException, JDOMException, Exception 00090 { 00091 ProfilesRepository.__add(in_profile.toXml()); 00092 } 00093 00094 /** 00095 * Given a profile, this method removes the associated profile from the repository. 00096 * @param in_profile Profile to remove. 00097 * @throws ProfilesRepositoryException 00098 * @throws JDOMException 00099 * @throws Exception 00100 */ 00101 public static void remove(AbstractConfiguration in_profile) throws ProfilesRepositoryException, JDOMException, Exception 00102 { 00103 ProfilesRepository.__remove(in_profile.toXml()); 00104 } 00105 00106 /** 00107 * Given a profit's name, this method removes the associated profile from the repository. 00108 * @param in_name The name of the profile to remove. 00109 * @throws ProfilesRepositoryException 00110 * @throws JDOMException 00111 * @throws Exception 00112 */ 00113 public static void remove(String in_name) throws ProfilesRepositoryException, JDOMException, Exception 00114 { 00115 if (null == ProfilesRepository.__profiles) { ProfilesRepository.init(); } 00116 Element conf = ProfilesRepository.__getProfileByName(in_name); 00117 if (null == conf) { throw new ProfilesRepositoryException("The name \"" + in_name + "\" is not associated to any profile."); } 00118 if (! ProfilesRepository.__profiles.getRootElement().removeContent(conf)) 00119 { throw new ProfilesRepositoryException("Could not remove profile \"" + in_name + "\"."); } 00120 // Write to disk. 00121 ProfilesRepository.__setUpdateDateTimeToNow(null); 00122 ProfilesRepository.__write(null); 00123 } 00124 00125 /** 00126 * Update a given profile. 00127 * @remark The removal uses the name of the profile 00128 * @param in_profile New profile. 00129 * @throws ProfilesRepositoryException 00130 * @throws JDOMException 00131 * @throws Exception 00132 */ 00133 public static void update(AbstractConfiguration in_profile) throws ProfilesRepositoryException, JDOMException, Exception 00134 { 00135 ProfilesRepository.__update(in_profile.toXml()); 00136 } 00137 00138 /** 00139 * Return a literal representation of the profiles' repository. 00140 * @return Return a literal representation of the profiles' repository. 00141 */ 00142 public static String print() throws Exception 00143 { 00144 if (null == ProfilesRepository.__profiles) { ProfilesRepository.init(); } 00145 return org.dbview.utils.Jdom.print(ProfilesRepository.__profiles); 00146 } 00147 00148 /** 00149 * Return an instance of a given profile's configuration's holder. 00150 * @remark The returned instance is initialized using the XML representation extracted from the repository. 00151 * @param in_name Name of the profile. 00152 * @return If the requested profile exists, then the method returns an instance of the configuration's holder. 00153 * Otherwise, it returns the value null. 00154 */ 00155 public static AbstractConfiguration getProfileInstance(String in_name) throws ConfigurationException, JDOMException, Exception 00156 { 00157 if (null == ProfilesRepository.__profiles) { ProfilesRepository.init(); } 00158 Element profile = ProfilesRepository.__getProfileByName(in_name); 00159 if (null == profile) { return null; } 00160 String target = ProfilesRepository.__getProfileTarget(profile); 00161 InputCatalog a = new InputCatalog(); 00162 AbstractConfiguration conf = (AbstractConfiguration)a.getAdaptor(target, "Configuration"); 00163 conf.fromXml(profile, null, null); 00164 return conf; 00165 } 00166 00167 /** 00168 * This method returns the list of all profiles' names stored in the profiles' repository. 00169 * @return The method returns the list of all profiles stored in the profiles' repository. 00170 * @throws JDOMException 00171 */ 00172 public static ArrayList<String> getProfilesNames() throws JDOMException 00173 { 00174 ArrayList<String> profiles = new ArrayList<String>(); 00175 XPath xpa = XPath.newInstance("configuration"); 00176 @SuppressWarnings("unchecked") 00177 List<Element> list = (List<Element>)xpa.selectNodes(ProfilesRepository.__profiles.getRootElement()); 00178 00179 for (int i=0; i<list.size(); i++) 00180 { 00181 Element e = list.get(i); 00182 profiles.add(e.getAttributeValue("name")); 00183 } 00184 00185 return profiles; 00186 } 00187 00188 /** 00189 * This method tries to locate a given profile given its name. 00190 * @param in_name Name of the profile to locate. 00191 * @return If the profile, identified by the given name exists, then it is returned. 00192 * Otherwise, the method returns the value null. 00193 * @throws JDOMException 00194 */ 00195 private static Element __getProfileByName(String in_name) throws JDOMException 00196 { 00197 XPath xpa = XPath.newInstance("configuration[@name='" + in_name + "']"); 00198 return (Element)xpa.selectSingleNode(ProfilesRepository.__profiles.getRootElement()); 00199 } 00200 00201 /** 00202 * Given a profile, this method returns its name. 00203 * @param in_profile Profile. 00204 * @return The method returns the profile's name. 00205 * @throws Exception 00206 */ 00207 private static String __getProfileName(Element in_profile) throws Exception 00208 { 00209 Attribute attr = in_profile.getAttribute("name"); 00210 if (null == attr) { throw new Exception("Unexpected error : Found a profile with no name!"); } 00211 return attr.getValue(); 00212 } 00213 00214 /** 00215 * Given a profile, this method returns the name of the associated input add-on. 00216 * @param in_profile Profile. 00217 * @return The method returns the name of the associated input add-on. 00218 * @throws Exception 00219 */ 00220 private static String __getProfileTarget(Element in_profile) throws Exception 00221 { 00222 Attribute attr = in_profile.getAttribute("target"); 00223 if (null == attr) { throw new Exception("Unexpected error : Found a profile with no target name!"); } 00224 return attr.getValue(); 00225 } 00226 00227 /** 00228 * This method creates an instance of class "File" that points to the profiles' repository. 00229 * @throws URISyntaxException 00230 * @throws Exception 00231 */ 00232 private static void __initFile() throws URISyntaxException, Exception 00233 { 00234 URL resources_url = JavaVm.locateResource(Conf.get("repositoriesDirName")); 00235 if (null == resources_url) { throw new Exception("Unexpected error : Can not locate the directory where the profile repository is kept (\"" + Conf.get("repositoriesDirName") + "\")."); } 00236 ProfilesRepository.__repository = new File(resources_url.toURI().getPath(), Conf.get("profilesRepository")); 00237 } 00238 00239 /** 00240 * This method writes the profiles to the file that contains the repository. 00241 * @param in_doc XML document to write (can be null!). 00242 * @warning The argument <i>in_doc</i> can be null. 00243 * @throws URISyntaxException 00244 * @throws Exception 00245 */ 00246 private static void __write(Document in_doc) throws URISyntaxException, Exception 00247 { 00248 if (null == ProfilesRepository.__repository) { ProfilesRepository.__initFile(); } 00249 XMLOutputter outputter = new XMLOutputter(); 00250 outputter.setFormat(org.jdom.output.Format.getPrettyFormat()); 00251 FileWriter fw = new FileWriter(ProfilesRepository.__repository); 00252 in_doc = null == in_doc ? ProfilesRepository.__profiles : in_doc; 00253 fw.write(outputter.outputString(in_doc)); 00254 fw.close(); 00255 } 00256 00257 /** 00258 * This method sets the value of the (XML) attribute "updated" to the current date ant time. 00259 * @param in_doc XML document to update (can be null!). 00260 * @warning The argument <i>in_doc</i> can be null. 00261 */ 00262 private static void __setUpdateDateTimeToNow(Document in_doc) 00263 { 00264 in_doc = null == in_doc ? ProfilesRepository.__profiles : in_doc; 00265 in_doc.getRootElement().setAttribute("updated", org.dbview.utils.Date.now()); 00266 } 00267 00268 /** 00269 * Add a new profile to the repository. 00270 * @param in_profile Profile to add. 00271 * @throws ProfilesRepositoryException 00272 * @throws Exception 00273 */ 00274 private static void __add(Element in_profile) throws ProfilesRepositoryException, JDOMException, Exception 00275 { 00276 if (null == ProfilesRepository.__profiles) { ProfilesRepository.init(); } 00277 String profile_name = ProfilesRepository.__getProfileName(in_profile); 00278 00279 // Make sure that the profile does not already exist. 00280 Element conf = ProfilesRepository.__getProfileByName(profile_name); 00281 if (null != conf) { throw new ProfilesRepositoryException("The name \"" + profile_name + "\" is already associated to a profile."); } 00282 00283 // Add the new profile. 00284 ProfilesRepository.__profiles.getRootElement().addContent(in_profile); 00285 00286 // Write to disk. 00287 ProfilesRepository.__setUpdateDateTimeToNow(null); 00288 ProfilesRepository.__write(null); 00289 } 00290 00291 /** 00292 * Update a given profile. 00293 * @remark The removal uses the name of the profile 00294 * @param in_profile New profile. 00295 * @throws ProfilesRepositoryException 00296 * @throws JDOMException 00297 * @throws Exception 00298 */ 00299 private static void __update(Element in_profile) throws ProfilesRepositoryException, JDOMException, Exception 00300 { 00301 // Delete the profile (the removal uses the name of the profile). 00302 ProfilesRepository.__remove(in_profile); 00303 00304 // Add the profile. 00305 ProfilesRepository.__add(in_profile); 00306 } 00307 00308 /** 00309 * Given a profile, this method removes the profile from the repository. 00310 * @param in_profile The profile to remove. 00311 * @throws ProfilesRepositoryException 00312 * @throws JDOMException 00313 * @throws Exception 00314 */ 00315 private static void __remove(Element in_profile) throws ProfilesRepositoryException, JDOMException, Exception 00316 { 00317 if (null == ProfilesRepository.__profiles) { ProfilesRepository.init(); } 00318 String profile_name = ProfilesRepository.__getProfileName(in_profile); 00319 ProfilesRepository.remove(profile_name); 00320 } 00321 }