1 package org.riverock.dbrevision.manager;
2
3 import org.riverock.dbrevision.Constants;
4 import org.riverock.dbrevision.utils.DbUtils;
5 import org.riverock.dbrevision.annotation.schema.db.Patch;
6 import org.riverock.dbrevision.db.Database;
7 import org.riverock.dbrevision.exception.ConfigFileNotFoundException;
8 import org.riverock.dbrevision.exception.CurrentVersionCodeNotFoundException;
9 import org.riverock.dbrevision.exception.DbRevisionPathNotFoundException;
10 import org.riverock.dbrevision.exception.ModuleNotConfiguredException;
11 import org.riverock.dbrevision.exception.DbRevisionException;
12 import org.riverock.dbrevision.manager.config.ConfigParserFactory;
13 import org.riverock.dbrevision.manager.dao.ManagerDaoFactory;
14
15 import java.io.File;
16 import java.io.FileInputStream;
17 import java.io.FileNotFoundException;
18 import java.io.IOException;
19 import java.util.ArrayList;
20 import java.util.List;
21
22 import org.apache.commons.lang.StringUtils;
23 import org.apache.log4j.Logger;
24
25
26
27
28
29
30 public class DbRevisionManager {
31 private final static Logger log = Logger.getLogger(DbRevisionManager.class);
32
33 private File path=null;
34
35 private File configFile=null;
36
37 private List<Module> modules = new ArrayList<Module>();
38
39 private Database database;
40
41 public DbRevisionManager(Database database, String dbRevisionPath) {
42 if (database ==null) {
43 throw new IllegalArgumentException("Database is null");
44 }
45 if (dbRevisionPath==null) {
46 throw new IllegalArgumentException("dbRevisionPath is null");
47 }
48 this.database = database;
49 this.path = new File(dbRevisionPath);
50 if (!path.exists()) {
51 throw new DbRevisionPathNotFoundException("DbRevision path not found: " + path.getAbsolutePath());
52 }
53 this.configFile = new File(path, Constants.CONFIG_FILE_NAME);
54 if (!configFile.exists()) {
55 throw new ConfigFileNotFoundException("Config file not found: " + configFile.getAbsolutePath() );
56 }
57 processConfigFile();
58 prepareCurrentVersions();
59 }
60
61 protected void finalize() throws Throwable {
62 destroy();
63 super.finalize();
64 }
65
66 public void destroy() {
67
68 if (modules!=null) {
69 for (Module module : modules) {
70 module.destroy();
71 }
72 modules.clear();
73 modules=null;
74 }
75 if (database!=null) {
76 if (database.getConnection()!=null) {
77 DbUtils.close(database.getConnection());
78 database.setConnection(null);
79 }
80 this.database=null;
81 }
82 }
83
84
85
86
87
88
89
90 public Module getModule(String name) {
91 for (Module module : modules) {
92 if (module.getName().equals(name)) {
93 return module;
94 }
95 }
96 return null;
97 }
98
99
100
101
102
103
104 public boolean isAllCompleted() {
105 for (Module module : modules) {
106 if (!module.isComplete()) {
107 return false;
108 }
109 }
110 return true;
111 }
112
113 private void processConfigFile() {
114 Config config;
115 FileInputStream inputStream=null;
116 try {
117 inputStream = new FileInputStream(configFile);
118 config = ConfigParserFactory.getConfigParser().parse(inputStream);
119 }
120 catch (FileNotFoundException e) {
121 throw new ConfigFileNotFoundException(e);
122 }
123 finally {
124 if (inputStream!=null) {
125 try {
126 inputStream.close();
127 }
128 catch (IOException e1) {
129 log.error("Error close input stream", e1);
130 }
131 }
132 }
133 for (ModuleConfig moduleConfig : config.getModuleConfigs()) {
134 modules.add( new Module(database, path, moduleConfig) );
135 }
136 }
137
138 public List<Module> getModules() {
139 return modules;
140 }
141
142 private void prepareCurrentVersions() {
143 List<RevisionBean> revisionBeans = ManagerDaoFactory.getManagerDao().getRevisions(database);
144 for (RevisionBean revisionBean : revisionBeans) {
145 Module module = getModule(revisionBean.getModuleName());
146 if (module!=null) {
147 markCurrentVersion(module, revisionBean);
148 }
149 else {
150 throw new ModuleNotConfiguredException("Module '"+ revisionBean.getModuleName()+"' not configured.");
151 }
152 }
153 }
154
155 private void markCurrentVersion(Module module, RevisionBean revisionBean) {
156 Version prevVersion = null;
157 for (Version version : module.getVersions()) {
158 version.setPreviousVersion(prevVersion);
159 if (prevVersion!=null) {
160 prevVersion.setNextVersion(version);
161 }
162 prevVersion = version;
163 }
164
165 boolean isFound = false;
166 for (Version version : module.getVersions()) {
167 if (version.getVersionName().equals(revisionBean.getCurrentVerson())) {
168 markAllCompleteProccesedVesion(version, revisionBean);
169 isFound = true;
170 break;
171 }
172 }
173 if (!isFound) {
174 throw new CurrentVersionCodeNotFoundException(
175 "Current version '"+revisionBean.getCurrentVerson()+"' not exist in configuration for module '"+revisionBean.getModuleName()+"'. " +
176 "Check '<db-revision-path>/config.xml' file."
177 );
178 }
179 Version v = module.getLastVersion();
180 if (v==null || v.isComplete()) {
181 module.setComplete(true);
182 }
183 }
184
185 private void markAllCompleteProccesedVesion(Version version, RevisionBean revisionBean) {
186 Version v;
187 if (version.getPatches().isEmpty()) {
188 if (StringUtils.isNotBlank(revisionBean.getLastPatch())) {
189 throw new DbRevisionException("Invalid value of lastPatch in database. Module: " + revisionBean.getModuleName()+", version: " + revisionBean.getCurrentVerson());
190 }
191 v = version;
192 }
193 else if (StringUtils.isBlank(revisionBean.getLastPatch())) {
194 v = version;
195 }
196 else {
197 if (version.getPatches().get(version.getPatches().size()-1).getName().equals(revisionBean.getLastPatch())) {
198 v = version;
199 }
200 else {
201 v = version.getPreviousVersion();
202 List<Patch> completed = new ArrayList<Patch>();
203 boolean isFound = false;
204 for (Patch patch : version.getPatches()) {
205 if (patch.getName().equals(revisionBean.getLastPatch())) {
206 completed.add(patch);
207 isFound = true;
208 break;
209 }
210 completed.add(patch);
211 }
212
213 if (isFound) {
214 for (Patch patch : completed) {
215 patch.setProcessed(true);
216 }
217 }
218 else {
219 throw new DbRevisionException("Value of lastPatch in database not equals to last value in config. Module: " + revisionBean.getModuleName()+", version: " + revisionBean.getCurrentVerson());
220 }
221 }
222 }
223
224 while (v!=null) {
225 v.setComplete(true);
226 v = v.getPreviousVersion();
227 }
228 }
229 }