package ameba.db.migration;
import ameba.core.Application;
import ameba.db.DataSourceManager;
import ameba.db.migration.resources.MigrationResource;
import org.glassfish.hk2.api.ServiceLocator;
import org.glassfish.jersey.server.ContainerRequest;
import javax.annotation.Priority;
import javax.inject.Inject;
import javax.inject.Singleton;
import javax.ws.rs.HttpMethod;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerRequestFilter;
import javax.ws.rs.container.PreMatching;
import javax.ws.rs.core.Form;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import java.io.IOException;
import java.util.Map;
/**
* <p>MigrationFilter class.</p>
*
* @author icode
*
*/
@PreMatching
@Priority(Integer.MIN_VALUE)
@Singleton
public class MigrationFilter implements ContainerRequestFilter {
private static final String FAVICON_ICO = "favicon.ico";
private boolean ran = false;
@Inject
private Application.Mode mode;
@Inject
private Application application;
@Inject
private ServiceLocator locator;
@Inject
private MigrationResource resource;
/**
* {@inheritDoc}
*/
@Override
public void filter(ContainerRequestContext req) throws IOException {
if (!ran) {
UriInfo uriInfo = req.getUriInfo();
String path = uriInfo.getPath();
if (path.equals(FAVICON_ICO) || path.endsWith("/" + FAVICON_ICO)) {
return;
}
path = "/" + path;
String migrationUri = MigrationResource.MIGRATION_BASE_URI + MigrationFeature.getMigrationId();
String repairUri = migrationUri + "/repair";
Map<String, Object> properties = application.getProperties();
Map failMigrations = resource.getFailMigrations();
if (!mode.isDev() && (path.equals(migrationUri) || path.equals(repairUri))
&& HttpMethod.GET.equals(req.getMethod())
&& failMigrations != null && !failMigrations.isEmpty()) {
repairView(req);
return;
} else if (path.equals(migrationUri) && HttpMethod.POST.equals(req.getMethod())) {
String desc = ((ContainerRequest) req).readEntity(Form.class).asMap().getFirst("description");
req.abortWith(
Response.ok().entity(resource.migrate(desc, MigrationFeature.getMigrationId())).build()
);
return;
} else if (path.equals(repairUri) && HttpMethod.POST.equals(req.getMethod())) {
req.abortWith(
Response.ok().entity(resource.repair(MigrationFeature.getMigrationId())).build()
);
return;
} else if (!mode.isDev() && path.equals(migrationUri) && HttpMethod.GET.equals(req.getMethod())) {
migrateView(req);
return;
} else if (!mode.isDev() && path.equals(repairUri) && HttpMethod.GET.equals(req.getMethod())) {
repairView(req);
return;
}
if (mode.isDev()) {
if (HttpMethod.GET.equals(req.getMethod())
&& failMigrations != null && !failMigrations.isEmpty()) {
repairView(req);
return;
}
for (String dbName : DataSourceManager.getDataSourceNames()) {
if (!"false".equals(properties.get("db." + dbName + ".migration.enabled"))) {
Migration migration = locator.getService(Migration.class, dbName);
if (migration.hasChanged()) {
migrateView(req);
return;
}
}
}
} else {
boolean change = false;
for (String dbName : DataSourceManager.getDataSourceNames()) {
if (!"false".equals(properties.get("db." + dbName + ".migration.enabled"))) {
Migration migration = locator.getService(Migration.class, dbName);
if (migration.hasChanged()) {
change = true;
break;
}
}
}
if (!change) {
if (failMigrations != null && !failMigrations.isEmpty()) {
change = true;
}
}
if (!change) {
ran = true;
}
}
}
}
private void repairView(ContainerRequestContext req) {
req.abortWith(
Response.serverError()
.entity(resource.repairView(MigrationFeature.getMigrationId()))
.type(MediaType.TEXT_HTML_TYPE)
.build()
);
}
private void migrateView(ContainerRequestContext req) {
req.abortWith(Response.fromResponse(
resource.migrateView(MigrationFeature.getMigrationId())
).status(500).build());
}
}