Authors Posts by pzepernick

pzepernick

12 POSTS 7 COMMENTS

0 5068

folder-with-file-icon-hi
Today I wanted to share a utility I whipped up. I wanted the utility to accept a File Object and be able to do the following:

  • Check if the file name exists, if it does NOT, return the File passed in.
  • Generate a random number between 1000 and 9999 and insert it before the file extension, or at the end of the name if there is no extension.
  • Repeat the process if necessary until we find a unique name.

Here is the class below free of any third party dependencies. You have my permission to use it however you see fit.

public class FileUtils {

    private static Random random = new Random();

    /**
     * 
     * @param f
     * @return
     *      A unique file name or the file passed in if it does not exist
     */
    public static File getUniqueFile(File f) {
        if(!f.exists()) {
            return f;
        }

        StringBuilder fsb = new StringBuilder(f.getName());
        int insertion = fsb.lastIndexOf(".");
        if (insertion == -1) {
            insertion = fsb.length();
        }


        int rand = randInt(1000, 9999);
        fsb.insert(insertion, rand);
        File randFile = new File(f.getParentFile(), fsb.toString());
        if(randFile.exists()) {
            //keep going until we get something unique
            return getUniqueFile(f);
        }

        return randFile;
    }


    public static int randInt(int min, int max) {
        return random.nextInt((max - min) + 1) + min;

    }

}

4 346101

tiff_to_pdfThis week I got to research and do some work on figuring out the best way to take a multipage tiff file and convert it to a PDF format. When I first started on this, I went immediately to iText as that was the only library I was familiar with. After getting a working example going, I checked out the license for the most current version of iText and realized that it cannot be used in any closed source applications without buying the license. This is what led me to begin searching for other Java PDF libraries.

I came across Apache PDFBox and saw that it had the ability to add images to the PDF, and even had a class to add a TIFF. I gave the TIFF example a try and I got a complaint about unsupported compression. After pondering this for a while, I had the thought of reading in each page of the tiff as a BufferedImage and then placing each one into the PDF as a JPG. This actually requires 2 libraries.

  1. commons-imaging
  2. pdfbox

The commons imaging can be substituted for something else if you can get a List from the Tiff. It is currently not released and is in the apache sandbox as a snapshot. Here is the maven dependency for it with the repository:


<repository> <id>apache.snapshots</id> <name>Apache Development Snapshot Repository</name> <url>https://repository.apache.org/content/repositories/snapshots/</url> <releases> <enabled>false</enabled> </releases> <snapshots> <enabled>true</enabled> </snapshots> </repository> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-imaging</artifactId> <version>1.0-SNAPSHOT</version> </dependency>

Here is the Maven dependency for pdfbox

        <dependency>
          <groupId>org.apache.pdfbox</groupId>
          <artifactId>pdfbox</artifactId>
          <version>1.8.9</version>
        </dependency>

Here is a example class that can be run against a directory of tiff images. All tiff files in the directory will be converted over to PDF.

package com.iws.export;

import java.awt.Dimension;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.channels.FileChannel;
import java.util.Iterator;
import java.util.List;

import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;

import org.apache.commons.imaging.Imaging;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.edit.PDPageContentStream;
import org.apache.pdfbox.pdmodel.graphics.xobject.PDJpeg;
import org.apache.pdfbox.pdmodel.graphics.xobject.PDXObjectImage;

import com.google.common.base.Stopwatch;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Image;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.io.FileChannelRandomAccessSource;
import com.itextpdf.text.pdf.PdfWriter;
import com.itextpdf.text.pdf.RandomAccessFileOrArray;
import com.itextpdf.text.pdf.codec.TiffImage;

public class QueueToPdf {

public static void main(String[] args) {
try {
new QueueToPdf().generatePdfFromTifPbox(new File("/mydir"));
} catch (Exception e) {
e.printStackTrace();
}
}

public void generatePdfFromTifPbox(File dir) {
for(final File f : dir.listFiles()) {

try (
PDDocument doc = new PDDocument();
)
{

List bimages = Imaging.getAllBufferedImages(f);
for(BufferedImage bi : bimages) {
PDPage page = new PDPage();
doc.addPage( page );
PDPageContentStream contentStream = new PDPageContentStream(doc, page);
try {
//the .08F can be tweaked. Go up for better quality, but the size of the PDF will increase
PDXObjectImage image = new PDJpeg(doc, bi, .08F);

Dimension scaledDim = getScaledDimension(new Dimension(image.getWidth(), image.getHeight()), page.getMediaBox().createDimension());
contentStream.drawXObject(image, 1, 1, scaledDim.width, scaledDim.height);
} finally {
contentStream.close();
}

}

doc.save( f.getAbsolutePath() + ".pdf");

} catch (Exception e) {
e.printStackTrace();
}
}
}

//taken from a stack overflow post http://stackoverflow.com/questions/23223716/scaled-image-blurry-in-pdfbox
//Thanks Gyo!
private Dimension getScaledDimension(Dimension imgSize, Dimension boundary) {
int original_width = imgSize.width;
int original_height = imgSize.height;
int bound_width = boundary.width;
int bound_height = boundary.height;
int new_width = original_width;
int new_height = original_height;

// first check if we need to scale width
if (original_width > bound_width) {
//scale width to fit
new_width = bound_width;
//scale height to maintain aspect ratio
new_height = (new_width * original_height) / original_width;
}

// then check if we need to scale even with the new height
if (new_height > bound_height) {
//scale height to fit instead
new_height = bound_height;
//scale width to maintain aspect ratio
new_width = (new_height * original_width) / original_height;
}

return new Dimension(new_width, new_height);
}

}

The only complaint I have about this solution is that it is doubling the size of the tiff at the currently JPG quality level. I was impressed that when I first tried iText, the PDF actually ended up being slightly smaller than the tiff file I was converting. I am not sure if there is some other way the jpeg could be compressed, or if it is just the tiff compression being better than jpeg that is doing it. Please feel free to share your thoughts, or other solutions.

0 3111

jquery_bumper.sh-600x600
Today I decided to revisit how to best allow only numerics in a text field.  In the past, I have done this on the keydown event and matched against the key to see if that key that was pressed was allowed in the field.  This can then stop any unwanted keys from being allowed into the field.  Usually, it becomes a little bit of a headache because you do want to allow the user to use backspace, delete, arrows, decimal, hyphen, etc…  Then there is checking to make sure the hyphen can only be at the beginning and only allowing 1 decimal point, etc.  It can get to become quite the headache with all of the different things to look for.

I found a post on Stackoverflow and I was intrigued by one of the solutions using the keyup approach, test the data, and then remove any non numerics from it. There was some pretty nifty regex on there, but a lot of them still seemed to have problems allowing more than 1 decimal and the such. Someone had mentioned about just using jQuery.isNumeric(). I decided to write an example of how this could be done using the jQuery function.

$(document).on('keyup', '.numeric-only', function(event) {
   var v = this.value;
   if($.isNumeric(v) === false) {
        //chop off the last char entered
        this.value = this.value.slice(0,-1);
   }
});

This will force the field to only contain numeric values. The one down side of doing it this way is that you see the non numeric char quickly appear and disappear. This is a great solution as long as that does not bother you.

Here is an example fiddle where you can see it in action.

Recently I started to write my CodeIgniter helper’s to use classes with static methods instead of writing global functions. This stops from having to check if the function name you are about to use already exists, and also allows the use of PHP namespaces if you desire.

Here is a example of how the helper functions are normally setup:

    if( !function_exists('longUniqueString')) {
            /**
          * Provides an extra long random unique String
          * 
          * @param $iterations (default 3)
          * @return String
          *          Random String
          */
         function longUniqueString($iterations = 3) {
             get_instance() -> load -> helper('string');
             $s = '';
             for($i = 0; $i < $iterations; $i++) {
                 $s .= random_string('unique');
             }

             return $s;
         }
    }

Here is the static method way of doing the same thing:

    class CMUtils {


        /**
         * Provides an extra long random unique String
         * 
         * @param $iterations (default 3)
         * @return String
         *          Random String
         */
        public static function longUniqueString($iterations = 3) {
            get_instance() -> load -> helper('string');
            $s = '';
            for($i = 0; $i < $iterations; $i++) {
                $s .= random_string('unique');
            }

            return $s;
        }
    }

The name of the php helper file can be anything you want. Let’s say this particular helper was called utils_helper.php . The code to call the helper would go something like this

    $this -> load -> helper('utils');
    $myStr = CMUtils :: longUniqueString();

0 3452

Occasionally it is necessary to obtain information about the table in a db schema to perform dynamic operations on the data. For example: if trying to save to a numeric db field, automatically validate to make sure the data being received is numeric. I ran across 2 items that I wanted to be able to get the information on for a column, but they were not available in the CI Meta Field Data.

The 2 pieces of information that I really needed to know were:

  1. Is this an auto incremented field?

  2. Does this field allow NULL?

I extended the CI_Model with MY_Model and added this method:

    protected function getTableMetaData($table) {


            //Replaced the default CI field_data so that we could determine if the field is a auto_increment

             /*
                Example object in the MetaData

                   stdClass::__set_state(array(
                 'Field' => 'coupon_no',
                 'Type' => 'bigint(20)',
                 'Null' => 'NO',
                 'Key' => 'PRI',
                 'Default' => NULL,
                 'Extra' => 'auto_increment',
              ))*/

    $fields = $this -> db -> query('DESCRIBE ' . $table) -> result();
            $md = array();
            foreach($fields as $field) {
                preg_match('/([a-zA-Z]+)((d+))?/', $field->Type, $matches);

                $type = (array_key_exists(1, $matches)) ? $matches[1] : NULL;
                $length = (array_key_exists(2, $matches)) ? preg_replace('/[^d]/', '', $matches[2]) : NULL;

                $F              = new stdClass();
                $F->name        = $field->Field;
                $F->type        = $type;
                $F->default     = $field->Default;
                $F->max_length  = $length;
                $F->primary_key = ( $field->Key == 'PRI' ? 1 : 0 );
                $F->auto_increment = strripos($field -> Extra, 'auto_increment') !== FALSE ? 1 : 0; 
                $F->allow_null = $field->Null === 'YES' ? TRUE : FALSE;

                $md[] = $F;
            }




        return $md;

    }

The 2 new properties on the field data are auto_increment which is a boolean and allow_null which is also a boolean. This is MySQL specific, so it would have to be tweaked for other DB’s.

0 6404

I recently made some updates to Ion Auth 2 to allow the user to login with their username or email address.  This was accomplished by creating another config setting called identity_alt.  This is optional and can be used to specify a secondary column which the user can use for their login. I am utilizing it for the email field, but really it can be linked to any other column on the user table.  This enhancement will force this secondary column to be unique for new users if it is specified.  

I have done a pull request to incorporate this into the core ion Auth code, and there is some debate on whether or not it should be there.  Please go there and weigh in, we would appreciate your feedback.

Feel free to grab the update from my fork if you would like to get going on it now.

0 4092

This morning I was creating a extra small bootstrap button linked with a drop down menu. I was really tight on space and noticed that the font size on the drop down menu did not correspond with the class that was put on the button to change it’s size. Here is a snippet of CSS that can be included to accomplish this.

.btn.btn-xs + ul.dropdown-menu > li > a {
    font-size: 12px;
}

The CSS Selector Explained

The selector is is looking for a button that contains the classes “btn” and “btn-xs”. The “+” looks for the first sibling element(on the same hierarchical level) to be a <ul> tag containing the css class “dropdown-menu”. It then must have a <li> directly under the <ul> followed by a <a> tag directly under the <li>. Phew, got all that…

I used firebug to look at the font-size that was being applied to the “btn-xs” by bootstrap and matched it.

Here is a fiddle I whipped up if you would like to see it in action. This same technique could be applied for the other bootstrap buttons sizes.

0 3506

Wow, it has been a month since my last post. Thought I would come on and provide everyone with an update of what I have been working on lately.

For the past week and a half I had the pleasure of trying to get a Java cache implementation working. I was caching 2 very large tables down locally from one of our applications at work that I am pulling data from. The system I am working with has a very simplistic SQL engine to access its files, but it does not support sub-queries. This usually leads to a lot of extra queries being done in a loop, putting extra load on the DB, and slowing down the process of getting at the data I want.

The light bulb finally went on when I had the idea to just cache these 2 tables using the PK as the cache key and for the value a map with the column names and value from the db for each row in the table. I had used EHCache in the past with success for some in memory caching, so I thought, I will just throw EHCache at this and be done. I basically wanted an eternal cache so I did not have to rebuild the entire cache from scratch every time I needed it. I got my cache all setup and built out, and caching to the disk. The problem was the cache was getting cleared out every time the JVM reloaded. I researched this a bit and found out I was missing an option on my cache setup to tell EHCache to reload from disk on start up. Ah ha I thought, this is going to totally rock, and then this happened:

RuntimeException: This feature is only available in the enterprise version

Nooooooo, how could this be, lol! I checked out the pricing for the Enterprise version and you had to call. We were not wanting to spend a lot of money on this project so I knew EHCache was not going to be working out for us at this point. I have nothing against paying for software by the way, and I am sure that EHCache is worth the money if you have the money to throw at it.

Well after lots of Googling and reading, I landed on Infinispan which also looked really nice. I really liked that this had a little bit more of a simplistic way of moving data in and out of the Cache than EHCache. With EHCache, everything has to be wrapped in Element like so:

//putting
Element e = new Element("myKey", objectToCache);
cache.put(e);

//getting
Element e = cache.get("myKey");
e.getObjectValue();

It was much more Map like with Infinispan

cache.put("myKey", objectToCache);

cache.get("myKey");

I did a simple test with Infinispan and was able to push a value to the cache, shut the cache down, and retrieve the value again when I fired the cache back up. Another wave of excitement sweeps over me as I move my existing EhCache code over to the Infinispan API. I am able to use their SingleFileCacheStore and build out the cache. I then start to use the cache and delight at the speed at which it is flying through the data not having to do my extra DB queries. But then I watch as it starts to go slower and slower GC, GC, GC, Out of Memory. NOOOoooooo! The objects that were getting serialized from the cache never seemed to get garbage collected. I spent a while researching this and ran into a bunch of dead ends.

Back to The Google I go….

I briefly tried JCS, but could not get the cache to reload from disk on start up. Thought maybe it was something stupid in my configuration. Went through the docs multiple times and posted a question on Stackoverflow with no success.

Yup you guessed it, back to Google AGAIN!

I finally landed on this gem, MapDB. It is actually built to be a database to store Java Objects and implements the Java Collections so you can work with it as a Map, List, etc. As of right now, I could not be happier. My Infinispan cache size was a 2GB file. This file is 500mb caching the same data. It is a little bit slower pushing the data into it. It has a Async option for writes that speeds it up quite a bit, but I was getting a concurrent modification exception when I had it turned on. I just shut it down for now as I was not really concerned with the speed at which my cache got created. I did not notice any significant speed differences when pulling the objects out of the DB. The memory usage stays very low, and I am quiet impressed with how fast they can go to the file and pull the information out without having it in memory. Here is the JavaDoc for anyone interested.

I would be very interested to know your thoughts / experiences with similar implementations.

3 8900

Today I got to write a jQuery plugin that styles a select with hierarchical data. The markup would normally look like this in HTML:

<select>
  <optgroup label="Swedish Cars">
    <option value="volvo">Volvo</option>
    <option value="saab">Saab</option>
  </optgroup>
  <optgroup label="German Cars">
    <option value="mercedes">Mercedes</option>
    <option value="audi">Audi</option>
  </optgroup>
</select>

You can see the result of this over at w3schools

This looks cool, but what if you want to allow the user to select the optgroup telling the back end script to grab that level and all under it? I whipped up a quick plugin which works off of data attributes to describe the hierarchy. Here is what the structure of the html looks like:

<select id="hierarchySelect" class="form-control">
    <option data-isparent="true"  data-level="1">Main Dept 1</option>
    <option data-isparent="false" data-level="2">Sub 01</option>
    <option data-isparent="false" data-level="2">Sub 02</option>
    <option data-isparent="true"  data-level="2">Sub 03</option>
    <option data-isparent="false" data-level="3">Sub of Sub</option>
    <option data-isparent="true"  data-level="1">Main Dept 2</option>
    <option data-isparent="false" data-level="2">Sub 01</option>
    <option data-isparent="false" data-level="2">Sub 02</option>
    <option data-isparent="false" data-level="2">Sub 03</option>
</select>

The data-isparent should be flagged as true when there are child options under it. The plugin assumes that the options are already in the correct order. The data-level describes how many levels deep the option is. This assists in the indentation of the option. The default indentation is 25px, but can be overridden in the options of the plugin.

$("#hierarchySelect").selectHierarchy();

Here is a working fiddle that can be used to see the plugin in action.

Here is a link to Download the plugin. I want to build in some additional options and push it out to github when I have a chance. I will update this post when that happens. In the mean time, feel free to use it however you would like.

0 5359

I recently needed to determine if a library was loaded in CI form my Model. I have the CI Rest library using the same model for a query and wanted to change the query if the system had a user logged in. I simply wanted to check and see if the Tank Auth library was loaded and grab the user id from it if it was. I ended up using the PHP function class_exists.

    if(class_exists('Ion_auth')) {
        //Include user specific query stuff here
    }