Skip to content

Commit

Permalink
[GEOT-4279] NADCON grid shift factory does not release channels on gr…
Browse files Browse the repository at this point in the history
…id files
  • Loading branch information
aaime committed Oct 7, 2012
1 parent 102eb44 commit e1b81df
Show file tree
Hide file tree
Showing 4 changed files with 179 additions and 69 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

import java.io.File;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLDecoder;

Expand Down Expand Up @@ -76,5 +77,41 @@ public static File urlToFile(URL url) {
}
return new File(path3);
}

/**
* A replacement for File.toURI().toURL().
* <p>
* The handling of file.toURL() is broken; the handling of file.toURI().toURL() is known to be
* broken on a few platforms like mac. We have the urlToFile( URL ) method that is able to
* untangle both these problems and we use it in the geotools library.
* <p>
* However occasionally we need to pick up a file and hand it to a third party library like EMF;
* this method performs a couple of sanity checks which we can use to prepare a good URL
* reference to a file in these situtations.
*
* @param file
* @return URL
*/
public static URL fileToURL(File file) {
try {
URL url = file.toURI().toURL();
String string = url.toExternalForm();
if (string.contains("+")) {
// this represents an invalid URL created using either
// file.toURL(); or
// file.toURI().toURL() on a specific version of Java 5 on Mac
string = string.replace("+", "%2B");
}
if (string.contains(" ")) {
// this represents an invalid URL created using either
// file.toURL(); or
// file.toURI().toURL() on a specific version of Java 5 on Mac
string = string.replace(" ", "%20");
}
return new URL(string);
} catch (MalformedURLException e) {
return null;
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -180,78 +180,89 @@ private NADConGridShift loadBinaryGrid(final URL latGridUrl, final URL longGridU
final int HEADER_BYTES = 96;
final int SEPARATOR_BYTES = 4;
final int DESCRIPTION_LENGTH = 64;
ReadableByteChannel latChannel;
ReadableByteChannel longChannel;
ReadableByteChannel latChannel = null;
ReadableByteChannel longChannel = null;
NADConGridShift gridShift = null;
ByteBuffer latBuffer;
ByteBuffer longBuffer;

// //////////////////////
// setup
// //////////////////////
latChannel = getReadChannel(latGridUrl);
latBuffer = fillBuffer(latChannel, HEADER_BYTES);

longChannel = getReadChannel(longGridUrl);
longBuffer = fillBuffer(longChannel, HEADER_BYTES);

// //////////////////////
// read header info
// //////////////////////
// skip the header description
latBuffer.position(latBuffer.position() + DESCRIPTION_LENGTH);

int nc = latBuffer.getInt();
int nr = latBuffer.getInt();
int nz = latBuffer.getInt();

float xmin = latBuffer.getFloat();
float dx = latBuffer.getFloat();
float ymin = latBuffer.getFloat();
float dy = latBuffer.getFloat();

float angle = latBuffer.getFloat();
float xmax = xmin + ((nc - 1) * dx);
float ymax = ymin + ((nr - 1) * dy);

// skip the longitude header description
longBuffer.position(longBuffer.position() + DESCRIPTION_LENGTH);

// check that latitude grid header is the same as for latitude grid
if ((nc != longBuffer.getInt()) || (nr != longBuffer.getInt())
|| (nz != longBuffer.getInt()) || (xmin != longBuffer.getFloat())
|| (dx != longBuffer.getFloat()) || (ymin != longBuffer.getFloat())
|| (dy != longBuffer.getFloat()) || (angle != longBuffer.getFloat())) {
throw new FactoryException(Errors.format(ErrorKeys.GRID_LOCATIONS_UNEQUAL));
}

// //////////////////////
// read grid shift data into LocalizationGrid
// //////////////////////
final int RECORD_LENGTH = (nc * 4) + SEPARATOR_BYTES;
final int NUM_BYTES_LEFT = ((nr + 1) * RECORD_LENGTH) - HEADER_BYTES;
final int START_OF_DATA = RECORD_LENGTH - HEADER_BYTES;

latBuffer = fillBuffer(latChannel, NUM_BYTES_LEFT);
latBuffer.position(START_OF_DATA); // start of second record (data)

longBuffer = fillBuffer(longChannel, NUM_BYTES_LEFT);
longBuffer.position(START_OF_DATA);

NADConGridShift gridShift = new NADConGridShift(xmin, ymin, xmax, ymax, dx, dy, nc, nr);

int i = 0;
int j = 0;
for (i = 0; i < nr; i++) {
latBuffer.position(latBuffer.position() + SEPARATOR_BYTES); // skip record separator
longBuffer.position(longBuffer.position() + SEPARATOR_BYTES);

for (j = 0; j < nc; j++) {
gridShift.setLocalizationPoint(j, i, longBuffer.getFloat(), latBuffer.getFloat());
}
try {
// //////////////////////
// setup
// //////////////////////
latChannel = getReadChannel(latGridUrl);
latBuffer = fillBuffer(latChannel, HEADER_BYTES);

longChannel = getReadChannel(longGridUrl);
longBuffer = fillBuffer(longChannel, HEADER_BYTES);

// //////////////////////
// read header info
// //////////////////////
// skip the header description
latBuffer.position(latBuffer.position() + DESCRIPTION_LENGTH);

int nc = latBuffer.getInt();
int nr = latBuffer.getInt();
int nz = latBuffer.getInt();

float xmin = latBuffer.getFloat();
float dx = latBuffer.getFloat();
float ymin = latBuffer.getFloat();
float dy = latBuffer.getFloat();

float angle = latBuffer.getFloat();
float xmax = xmin + ((nc - 1) * dx);
float ymax = ymin + ((nr - 1) * dy);

// skip the longitude header description
longBuffer.position(longBuffer.position() + DESCRIPTION_LENGTH);

// check that latitude grid header is the same as for latitude grid
if ((nc != longBuffer.getInt()) || (nr != longBuffer.getInt())
|| (nz != longBuffer.getInt()) || (xmin != longBuffer.getFloat())
|| (dx != longBuffer.getFloat()) || (ymin != longBuffer.getFloat())
|| (dy != longBuffer.getFloat()) || (angle != longBuffer.getFloat())) {
throw new FactoryException(Errors.format(ErrorKeys.GRID_LOCATIONS_UNEQUAL));
}

// //////////////////////
// read grid shift data into LocalizationGrid
// //////////////////////
final int RECORD_LENGTH = (nc * 4) + SEPARATOR_BYTES;
final int NUM_BYTES_LEFT = ((nr + 1) * RECORD_LENGTH) - HEADER_BYTES;
final int START_OF_DATA = RECORD_LENGTH - HEADER_BYTES;

latBuffer = fillBuffer(latChannel, NUM_BYTES_LEFT);
latBuffer.position(START_OF_DATA); // start of second record (data)

longBuffer = fillBuffer(longChannel, NUM_BYTES_LEFT);
longBuffer.position(START_OF_DATA);

gridShift = new NADConGridShift(xmin, ymin, xmax, ymax, dx, dy, nc, nr);

int i = 0;
int j = 0;
for (i = 0; i < nr; i++) {
latBuffer.position(latBuffer.position() + SEPARATOR_BYTES); // skip record separator
longBuffer.position(longBuffer.position() + SEPARATOR_BYTES);

for (j = 0; j < nc; j++) {
gridShift.setLocalizationPoint(j, i, longBuffer.getFloat(), latBuffer.getFloat());
}
}

assert i == nr : i;
assert j == nc : j;
} finally {
if(latChannel != null) {
latChannel.close();
}
if(longChannel != null) {
longChannel.close();
}
}

assert i == nr : i;
assert j == nc : j;


return gridShift;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ public NADCONTransform(final URI latGridName, final URI longGridName)
this.gridShiftTransform = grid.getMathTransform();
}

URL locateGrid(URI uri ) throws FactoryException {
protected URL locateGrid(URI uri ) throws FactoryException {
String grid = uri.toString();
for (GridShiftLocator locator : ReferencingFactoryFinder.getGridShiftLocators(null)) {
URL result = locator.locateGrid(grid);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package org.geotools.referencing.operation.transform;

import static org.junit.Assert.*;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

import org.geotools.referencing.factory.gridshift.DataUtilities;
import org.geotools.referencing.factory.gridshift.NADCONGridShiftFactory;
import org.geotools.referencing.factory.gridshift.NADConGridShift;
import org.junit.Test;
import org.opengis.referencing.FactoryException;

public class NADCONGridShiftFactoryTest {

@Test
public void testReleaseGrids() throws IOException, FactoryException {
File gridShifts = new File("src/test/resources/org/geotools/referencing/factory/gridshift");
File las = new File(gridShifts, "stpaul.las");
File los = new File(gridShifts, "stpaul.los");

File tlas = new File("./target/stpaul.las");
File tlos = new File("./target/stpaul.los");
copyFile(las, tlas);
copyFile(los, tlos);

NADCONGridShiftFactory factory = new NADCONGridShiftFactory();
NADConGridShift shift = factory.loadGridShift(DataUtilities.fileToURL(tlas), DataUtilities.fileToURL(tlos));
// minor checks on the grid
assertNotNull(shift);

// now the good part, try to delete the files, on windows this will fail
// unless the sources were properly closed
assertTrue(tlas.delete());
assertTrue(tlos.delete());
}

private void copyFile(File src, File dst) throws IOException {
FileInputStream fis = null;
FileOutputStream fos = null;
try {
fis = new FileInputStream(src);
fos = new FileOutputStream(dst);
byte[] buffer = new byte[4096];
int read = 0;
while((read = fis.read(buffer)) > 0) {
fos.write(buffer, 0, read);
}
} finally {
if(fis != null) {
fis.close();
}
if(fos != null) {
fos.close();
}
}

}
}

0 comments on commit e1b81df

Please sign in to comment.